Friday 4 November 2011

iOS Code Coverage with Cobertura

Since I wrote this post, XCode has been updated somewhat, more concise xcodebuild commands can be found here:  http://jonboydell.blogspot.co.uk/2013/01/i-have-previously-written-couple-of.html

I am 100% sure that everyone who develops anything for the iOS platform is a Software Engineer and not a Bedroom Based Homebrewer then we all use Continuous Integration to ensure that our builds are never broken and to provide insightful metrics into the quality of our code.

There is a tool called gcovr (https://software.sandia.gov/trac/fast/wiki/gcovr) that can be used to turn the files generated by XCode into something more readable and something that, with the Jenkins Cobertura plugin, you can use to trigger build-fail thresholds in Jenkins and to click through your code base to find out where the unit test coverage is weakest.

gcovr is a python script that converts gcov (the tool that comes with XCode for generating code coverage files) output into a more readable XML format or into command line output.

Firstly

Download gcovr and copy it into somewhere useful on your filesystem.  Then set the following project build settings in XCode:  "Generate Test Coverage Files" to Yes and "Instrument Program Flow" to Yes.  This generates the .gcno and .gcda files needed for gcovr to generate something more readable.

Run gcovr
 
1. Change directory to your project folder (the one where your .xcodeproj file sits)
2. Run:

gcovr -r `pwd` -e .*${TESTTARGET}.* -x > coverage.xml


Where ${TESTTARGET} is the name of the tests target that XCode creates for you when you have the "include unit tests" option ticked on project creation.  This prevents the code coverage of the unit tests being reported.

3. Check the output coverage.xml to make sure that there's something in it that you recognise. (I say this as the best way to check it's worked is to just eyeball the file).


Integrate with Jenkins

My iOS CI works by executing a command line script in a Jenkins job. The script builds my project using some command much like this:

xcodebuild -sdk iphonesimulator -project myProject.xcodeproj -target myProjectTests -configuration Debug clean TEST_AFTER_BUILD=YES TEST_HOST=

You will have had to configure the myProjectTests target to produce GCOV code coverage data. Then to integrate the GCOVR step, add this to your build:

gcovr -r `pwd` --exclude '.*myProjectTests.*' --xml > myProjectDir/coverage.xml

n.b. It's having the correct setting for the -r option that makes the source code highlighting feature of the Cobertura plugin work properly.

Bosh! Now install the Cobertura plugin into Jenkins, enable it for your CI build, check the "Publish Cobertura Code Coverage Reports" and enter "**/coverage.xml" into the "Cobertura xml report pattern" box. Press Save. Run the build. You should now have a "Coverage Report" icon in your Jenkins job view which if you click on it will give you some headline data about your test code coverage plus clickable links to your source code which should give you a detailed breakdown per line of code on its coverage status.

Monday 17 October 2011

XCode, iOS and Code Coverage

Since I wrote this post, XCode has been updated somewhat, more concise xcodebuild commands can be found here:  http://jonboydell.blogspot.co.uk/2013/01/i-have-previously-written-couple-of.html 

There are a lot of smart people who use the internet to publish the answers to problems that I encounter, mostly whilst at work, but sometimes when I want to catch a mouse or sew a button back onto my jeans. These people usually post, in one easily Googled page, step-by-step instructions to be repeated back much like a spell. Step 1 to Step X and your mouse is caught, your button sewn or a snippet of code copied and pasted into a project on which I am working from someones blog (attribution optional).

Today though, I done some discovering of my own and am now reasonably assured that I have got XCode running a code coverage tool of some form and producing some results in which I have some confidence.

So, what's the spell?

1. Create (if you haven't already) a testing target for your project
2. Change the target (just the testing target, not the whole project) options as follows:
2a. "Compiler for C/C++/Objective-C" to "Apple LLVM Compiler 3.0"
2b. "Generate Test Coverage Files" to "Yes"
2c. "Instrument Program Flow" to "Yes"
3. No other compiler or linker flags, and indeed, some linker flags may make the code coverage generator go wonky (specifically -all_load), I got a "402" error at compile time in one project and a break point error (at the same place) in another:

error: fopen$UNIX2003 called from function llvm_gcda_start_file

4. Add the following library to the "Build Phases" of the test target. That is:
4a. Go test target settings then "Build Phases" tab
4b. Go "Link Binary With Libraries"
4c. Go "+", then "Add Other.."
4d. Go "/Developer/usr/lib/libprofile_rt.dylib" which will add it to the list of things to link

Should work, spangle your "Test" schema. See what happens. This will generate a bunch of .gcda files in the build directory of your project. Which is hard to find. Try going "Organiser" then "Projects" (select your project), then click on the tiny grey arrow next to the "Derived Data" line (not the delete button). Then from the finder window, go "Build", "Intermediates", , "Debug-iphonesimulator", .build, "Objects-normal", .

If you're into a bit more than that, get the gcovr python script from here: https://software.sandia.gov/trac/fast/downloader (it's in the FAST library, under scripts, documentation here: https://software.sandia.gov/trac/fast) and run it from the ridiculous build directory above, will give you a pretty print of your code coverage. And if you're into a bit more than that have gcover generate xml and stuff it into Cobertura (gcovr --xml >/somewhere/useful/no/really.xml)

(I am using XCode 4.2 with iOS 5.0)