› Shell helper: running KDE unit tests (ctests) the easy way 
Thu, 03/26/2009 - 03:09
Unit tests are in my eyes a very important part of programming. KDE uses them, KDevelop does - the PHP plugin I help writing does as well. cmake comes with a ctest program which does quite well to give you a quick glance on which test suite you just broke with your new fance feature :)
But I am very dissatisfied with it. Right now I usually do the following
# lets assume I'm in the source directory cb && ctest # look for failed test suites cd $failed_test_suite_path ./$failed_test_suite.shell | less # search for FAIL cs cd $to_whereever_I_was_before
That’s pretty much for just running a test. Especially all that cding and lessing became very tedious. Tedious is good, because I eventually fix it:
introducing kdetest
I wrote a bash function (with autocompletion!!!) called kdetest. Calling it without any parameter will run all test suites and gives a nice report of failed functions at the end. Here’s an example (run via cs php && kdetest).
kdetest # ... lots of test output --- ALL PASSED TESTS --- ... PASS : Php::TestCompletion::implementMethods() PASS : Php::TestCompletion::inArray() PASS : Php::TestCompletion::cleanupTestCase() 143 passed tests in total --- ALL FAILED TESTS --- FAIL! : Php::TestCompletion::newExtends() Compared values are not the same FAIL! : Php::TestCompletion::updateExtends() '! forbiddenIdentifiers.contains(item->declaration()->identifier().toString())' returned FALSE. () FAIL! : Php::TestCompletion::updateExtends() '! forbiddenIdentifiers.contains(item->declaration()->identifier().toString())' returned FALSE. () FAIL! : Php::TestCompletion::updateExtends() Compared values are not the same FAIL! : Php::TestCompletion::newImplements() Compared values are not the same FAIL! : Php::TestCompletion::updateImplements() Compared values are not the same 6 failed tests in total
usage
kdetest, i.e. without any arguments runs all tests in this directory and belowkdetest path/to/test.shell ...runs that test suite only,...can by any argument the test suite accepts.
autocompletion
kdetest comes with full support for autocompletion of tests and functions, for example:
milian@odin:~/projects/kde4/php$ kdetest TABTAB completion/tests/completiontest.shell duchain/tests/expressionparsertest.shell parser/test/lexertest.shell duchain/tests/duchaintest.shell duchain/tests/usestest.shell milian@odin:~/projects/kde4/php$ kdetest duchain/tests/usestest.shell TABTAB classAndConstWithSameName classSelf interfaceExtendsMultiple staticMemberFunctionCall classAndFunctionWithSameName constAndVariableWithSameName memberFunctionCall staticMemberVariable classConstant constant memberFunctionInString variable classExtends constantInClassMember memberVariable variableTwoDeclarations classImplements functionAndClassWithSameName memberVarInString variableTwoDeclarationsInFunction classImplementsMultiple functionCall newObject varInString classParent interfaceExtends objectWithClassName
the code
You can find the code below, or you can obtain the most up-to-date version on github. Just head over to my shell-helpers repo and peek into the bash_setup_kde4_programming file.
# run a given unit-test or all via ctest function kdetest { local tests test args old_pwd tmpfile; old_pwd=$(pwd) cb tests=$(LANG=en_US.UTF-8 ctest -N -V | grep "Test command:" | cut -c $(echo "Test command: $(pwd)/" | wc -c)-) if [[ "$tests" == "" ]]; then echo "this directory does not contain any unit tests!" echo cd "$old_pwd" return 1 fi tmpfile=/tmp/testoutput_$$ if [[ "$1" != "" ]]; then test=$1 shift 1 args=$@ if [ ! -f "$test" ] || ! in_array "$test" $tests ; then echo "could not find unittest '$test'. available are:" echo $tests echo cd "$old_pwd" return 1 fi ./$test -maxwarnings 0 $args | tee -a "$tmpfile" echo else # run all tests for test in $tests; do ./$test -maxwarnings 0 | tee -a "$tmpfile" done fi echo echo " --- ALL PASSED TESTS --- " grep --color=never "^PASS " "$tmpfile" echo echo $(grep -c "^PASS " "$tmpfile")" passed tests in total" echo echo " --- ALL FAILED TESTS --- " grep --color=never "^FAIL!" "$tmpfile" echo echo $(grep -c "^FAIL!" "$tmpfile")" failed tests in total" rm "$tmpfile" cd "$old_pwd" } # completion for kdetest function _kdetest { local tests; old_pwd=$(pwd) cb tests=$(LANG=en_US.UTF-8 ctest -N -V | grep "Test command:" | cut -c $(echo "Test command: $(pwd)/" | wc -c)-) COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" if [[ "$prev" == "kdetest" ]]; then # completion of tests COMPREPLY=( $(compgen -W "${tests}" -- ${cur}) ) elif in_array "$prev" $tests; then # completion of available functions COMPREPLY=( $(compgen -W "$(./$prev -functions 2>/dev/null | cut -f 1 -d \( )" -- ${cur}) ) fi cd "$old_pwd" } complete -F _kdetest kdetest # see http://ftp.hu.freebsd.org/pub/linux/distributions/frugalware/frugalware-testing/t/functions.sh function in_array { local i needle=$1 shift 1 # array() undefined [ -z "$1" ] && return 1 for i in $* do [ "$i" == "$needle" ] && return 0 done return 1 }
Comments
cool - sound Thu, 03/26/2009 - 08:12 — Niko (not verified)
cool - sound useful! (especially the tab-completion :D)
You know that ctest puts the Thu, 03/26/2009 - 11:42 — Alexander Neundorf (not verified)
You know that ctest puts the output from all tests into <builddir>/Testing/Temporary/LastTest.log ?
I.e. you don’t have to rerun the test to see the output.
If you run ctest with “-V” (verbose) you will also get more output while the tests are running.
Is the shell function you wrote in any way KDE-specific ? If not, why not renaming it so other see it doesn’t have any KDE dependencies and maybe put it in the cmake wiki ?
Or could ctest be enhanced so it does what you want ?
Alex
Nope, I did not know that Thu, 03/26/2009 - 12:05 — Milian Wolff
Nope, I did not know that
LastTest.logexisted. I might be able to leverage that in my script. Yet the log alone won’t help me much since manually doingless <builddir>/Testing/Temporary/LastTest.logeverytimectestreports a failed testsuite is still a royal PITA :)As far as I remember
ctest -Vstill does not output theQDEBUGlines for example - often essential to understand what’s going wrong. Or something else was not satisfying, don’t remember - but I’ve checked that flag.And
kdetestis KDE-specific in the way that it depends oncb, i.e. on a build environment setup for KDE as described on techbase. You could of course build non-KDE programs in that environment.Improving
ctestwould be the best, but I doubt I could have been able to get to a point near whatkdetestdoes in around an hour.Post new comment