Incorrect Xcode code coverage results when testing exceptions

I am creating a static library for iOS and trying to get code coverage data for its unit tests. I use CoverStory to visualize generated code coverage files.

I get the correct information for most tests.

However, any test that verifies that an exception should be thrown is not marked as checked.

For example, the method

- (void)shouldThrow:(BOOL)throw { if (throw) @throw [NSException exception...]; NSLog(@"not thrown"); } 

Tested with test

 - (void)testShouldThrow { STAssertThrows( [myObject shouldThrow:YES], @"Should have thrown an exception"); STAssertNoThrow( [myObject shouldThrow:NO], @"Should not have thrown an exception"); } 

Skips all tests (i.e., the exception is thrown correctly). However, the code coverage does not show 100% - the line with @throw on is not marked as verified.

Any ideas?

+6
source share
2 answers

The line with @throw on it is not completed (because an exception is thrown), so it does not become marked as closed. You may indicate an error, but it is probably quite difficult to fix. If this is a single line in a branch statement, it can be very difficult to determine if it has been tested, but if there are lines before those that were executed, you just need to assume that this was also the case.

It’s bad that you can never reach 100%.

+3
source

An even worse problem is that it seems that the line counts before @throw in the same condition block are also closed. Therefore, simply writing the code before @throw as a marker will not help solve the problem.

However, I found that conditions, including variables ("if (YES)", "if (1 == 1)" not in cases, "are always lockable. Thus, the difficult thing we could do is first define a trivial condition variable, and then add a condition test, including this variable before @throw.

 static BOOL __trivialYES = YES; //for cover @throw, and never use 'const' 

then

 if(__trivialYES) @throw ...; 

This should help solve the problem, and for your convenience, you can define your own macro to do this.

 #define #throw if (__trivialYES) 

and then the throw statement:

 #throw ...; 

and this is likely to make the coverage test more effective.

PS: "#throw" is just a macro example. This is the same as another macro. "#" is just a valid character (for some precompilers) that makes it special.

0
source

Source: https://habr.com/ru/post/910794/


All Articles