| |||||||
Supported cards Downloads UMTS info Authors Sponsors Extra docs Developer's mailing list |
How to enable code coverage on the umtsmon module testsIntroductionThe umtsmon project contains several module tests in the umtsmon/test directory. Of course, it would be interesting to see how much of the code actually gets covered by these module tests. This page explains how to use gcov (see its man page) to do code coverage analysis. PreparationsIn order to enable code coverage logging, you need to compile all code again with specific extra compiler flags. These are already mentioned in test/GenericTestPro.inc but are outcommented in CVS: ### uncomment these two lines for compiling with code coverage instrumentation #QMAKE_CXXFLAGS_DEBUG += -fprofile-arcs -ftest-coverage #QMAKE_LFLAGS_DEBUG += -fprofile-arcs -ftest-coverageSecondly, you need to modify the location of the object files to the current directory. This is needed because otherwise, gcov won't be able to figure out which graph files belong to which source files. In the same file, you have to change OBJECT_DIR = .obj to read . instead of .obj. CompilationNow we need to run QT3's qmake and make to actually recompile all source code. Note that all required source files will be recompiled: the location changed, remember? RunningThis is the easy part: just run the application as usual. It will create *.gcda and *.gcno files for each source file or include file. Of course, the execution speed drops significantly due to all the logging it needs to do. gcov NetworkChangerTest_main.cpp gcov ../../src/controller/NetworkChanger.cpp gcov ../../src/model/Query.cpp gcov ../../.ui/networkoperatorwizard.cppwill create reports (the *.gcov files) for the relevant headers and source files which have a graph file in the current directory. These files contain ASCII text with the results AnalysisLet's look at a fragment of such file: 8: 108:Query::ReturnCode Query::run() -: 109:{ -: 110: // safety net 8: 111: assert(theSerialPortPtr != NULL); 8: 112: if (theSerialPortPtr == NULL) -: 113: { #####: 114: return NO_DEVICE; -: 115: } -: 116: -: 117: // more safety net: lock the mutex 8: 118: assert(hasLock == false); 8: 119: if (theQueryMutex.tryLock()==FALSE) -: 120: { #####: 121: hasLock = false; #####: 122: DEBUG5("Query instance %p trylock FAILED\n", this); #####: 123: return NO_LOCK; -: 124: }As you can see, the output contains all of the source code, including line numbers. Any line that doesn't contain executable code starts with a '-', otherwise it will either contain a number (the line has been executed X times) or '####', indicating that the line never has been executed. Viewing the above output, it shows that all special situations, like error conditions, have not been executed. That is usually unwanted behaviour - a good test case excerts both good and bad behavior. Browsing through results, you'll notice that not all lines have been executed. gcov actually tells how much lines were touched during the run: File '../../src/base/SerialPort.cpp' Lines executed:25.29% of 174 ../../src/base/SerialPort.cpp:creating 'SerialPort.cpp.gcov'Note that a percentage below 80% is generally considered to be too low. Achieving 100% is rather difficult - and many obscure error situations may not warrant spending time to write test code for. Advanced TopicsOf course, some files are exerted by several tests - a good example is the Query class, which is used by the majority of the test cases, and each test case touches diffent parts of the code. gcov by itself is capable to add data of multiple runs into the same graph files - allowing to run all tests and only then generate reports.
This way, running both NetworkOperatorWizardTester and NetworkChangerTester, you get a code coverage of 81.7% on NetworkChanger.cpp, 70.8% on networkoperatorwizard.ui.h and 97.3% of OperatorList.cpp. That's good. |
||||||
UMTSmon (C) 2006,2007,2008 Klaas van Gend and others, licensed under the GPL v2 license | hosted by SourceForge.net: | Sponsored by NLNet Foundation: | |