Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xcode5 Code Coverage (from cmd-line for CI builds)

How can I generate code coverage with Xcode 5 and iOS7?

Prior to upgrading I was getting code coverage just fine. Now I can't see any *.gcda files being produced.

The cmd-line that I'm using is:

xcodebuild -workspace ${module.name}.xcworkspace test -scheme ${module.name} -destination OS=${module.sdk.version},name=iPad -configuration Debug

Works with AppCode

  • When I execute the tests via AppCode I can see *.gcda files being produced in ~/Library/Caches/appCode20/DerivedData. . . I need this to work for my Continuous Integration builds.

Works from Xcode IDE

  • Also works from Xcode IDE. . . is there a cmd-line that will produce coverage, or is this an Xcode bug?
like image 235
Jasper Blues Avatar asked Aug 23 '13 04:08

Jasper Blues


People also ask

How do I get code coverage in Xcode?

Enabling Code Coverage in Xcode Code coverage is enabled in the scheme editor. Click the Covered scheme and choose Edit Scheme.... Select Test on the left and check the checkbox Gather coverage data. That is it.

What is Xccov?

xccov is a new command-line utility for inspecting the contents of Xcode coverage reports. It can be used to view coverage data in both human-readable and machine parseable format. See the man page for more information about the tool. ( Xcode 9.3b3)

How do I display code coverage?

On the Test menu, select Analyze Code Coverage for All Tests. You can also run code coverage from the Test Explorer tool window. Show Code Coverage Coloring in the Code Coverage Results window. By default, code that is covered by tests is highlighted in light blue.

How do you use code coverage?

To calculate the code coverage percentage, simply use the following formula: Code Coverage Percentage = (Number of lines of code executed by a testing algorithm/Total number of lines of code in a system component) * 100.


1 Answers

The following is a fix for SenTestKit - simply add this class to your Tests target. Something similar should be possible to do with XCTest

@interface VATestObserver : SenTestLog

@end

static id mainSuite = nil;

@implementation VATestObserver

+ (void)initialize {
    [[NSUserDefaults standardUserDefaults] setValue:@"VATestObserver" forKey:SenTestObserverClassKey];

    [super initialize];
}

+ (void)testSuiteDidStart:(NSNotification*)notification {
    [super testSuiteDidStart:notification];

    SenTestSuiteRun* suite = notification.object;

    if (mainSuite == nil) {
        mainSuite = suite;
    }
}

+ (void)testSuiteDidStop:(NSNotification*)notification {
    [super testSuiteDidStop:notification];

    SenTestSuiteRun* suite = notification.object;

    if (mainSuite == suite) {
        UIApplication* application = [UIApplication sharedApplication];
        [application.delegate applicationWillTerminate:application];
    }
}

and add

extern void __gcov_flush(void);

- (void)applicationWillTerminate:(UIApplication*)application {
    __gcov_flush();
}

Why is this working?

Tests and the tested application are compiled separately. Tests are actually injected into the running application, so the __gcov_flush() must be called inside the application not inside the tests.

The little magic with the observer only enables us to check when the tests are going to end and we trigger __gcov_flush() to be called inside the app.

like image 159
Sulthan Avatar answered Sep 23 '22 11:09

Sulthan