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)

3 comments:

  1. GRRREAT! Spent a whole day trying to get the setup right before finding this post. Totally solved my problems. Thanks a lot!

    ReplyDelete
  2. Great post!

    I have managed to do this with only application test though. according to the xcode4 app dev workflow, i did not duplicate the original app target as a separate target to host the unit test, so i directly changed the build setting to generate the code coverage on the original target with is involved with a scheme that does the test. All works fine on Simulator with code coverage and everything. however I cant get the same setting to build for device.

    error> ld: library not found for -lprofile_rt

    any hint how to fix this? Thanks!

    ReplyDelete
  3. I have code coverage data generated such that the files are in i386 folder. When trying to run gcovr command it seems to be finding the .gcda files but doesn't output anything.

    I run the command from i386 folder.

    Command: gcovr -r `pwd` -v

    Output:
    Running gcov: 'gcov /Users/abc/Library/Developer/Xcode/DerivedData/viewer-evgaabclrjcouydwveuptwroeofm/Build/Intermediates/viewer.build/Coverage-iphonesimulator/viewer_generic/viewer_generic.build/Objects-normal/i386/FILE_NAME.gcda --branch-counts --branch-probabilities --preserve-paths --object-directory /Users/abc/Library/Developer/Xcode/DerivedData/viewer-evgaabclrjcouydwveuptwroeofm/Build/Intermediates/viewer.build/Coverage-iphonesimulator/viewer_generic/viewer_generic.build/Objects-normal/i386' in '/Users/abc/Library/Developer/Xcode/DerivedData/viewer-evgaabclrjcouydwveuptwroeofm/Build/Intermediates/viewer.build/Coverage-iphonesimulator/viewer_generic/viewer_generic.build/Objects-normal/i386'
    Parsing coverage data for file /Users/abc/Documents/Perforce/DPS-MacBookPro/depot/sandbox/Viewer-Labatt/Blue/viewers/ipadviewer/iphone/apps/viewer/Classes/view/zooming/FILE_NAME.mm
    Filtering coverage data for file /Users/abc/Documents/Perforce/DPS-MacBookPro/depot/sandbox/Viewer-Labatt/Blue/viewers/ipadviewer/iphone/apps/viewer/Classes/view/zooming/FILE_NAME.mm
    Gathered coveraged data for 0 files
    ------------------------------------------------------------------------------
    File Lines Exec Cover Missing
    ------------------------------------------------------------------------------
    ------------------------------------------------------------------------------
    TOTAL 0 0 --%
    ------------------------------------------------------------------------------

    ReplyDelete