Strange code coverage issue

Xcode 9.3


Seeing a very odd issue with code coverage. I have two unit tests which ultimately test every branch in the following init function (put breakpoints to double-check that). Yet code coverage is putting red in the gutter along with a zero next to the lines in the if-blocks.


Build is debug and code coverage turned on. I have not seeing the issue in other classes.


init(data aData: Data?) {    // Function called 482 times during full unit test run
   index = 0

    let theLength : Int

    if let theData = aData {
       theLength = theData.count     // Code coverage shows zero here and zone is colored red
       data = theData
    } else {                          // Code coverage shows 482 here (which cannot be since the if-block is reached 90%+)
        theLength = 0
       data = Data()
    }

    length = theLength
}


Same exact thing happens for a simple test class. Unit test created two instances, one passing in a 2, the other 3. Breakpoints prove both are hit, yet code coverage not reflecting that:


class IIFoo {

  let s : String

  init(x anX: Int) {      // Code coverage shows 2 here

      if anX % 2 == 0 {
          s = "even"      // Shows 0 here and zone is colored red
      } else {            // Shows 2 here, zone is red and shows some diagonal lines in the coverage count area.
          s = "odd"
      }
  }
}

Replies

Hi,


I have the same issue in few classes on my project.

According to the Xcode 9.3 release note, some udpates have been done on code coverage tools, so it looks an issue has been introduced.


The

gcov
tool for code coverage testing has been reimplemented. The new version uses the
llvm-cov
tool from the LLVM project. It is functionally equivalent to the old version for all significant features. The location of
gcov
within Xcode has also moved, use xcrun to invoke it. If you find problems, please file bug reports. For this release, you can still use the old version of
gcov
from GCC, which is available as
gcov-4.2
. (11919694)


We can apparently revert back to the previous version, but I am not sure how to it... I tried to set "Generate Legacy Test Coverage Files" in the setting of my project to "Yes", but it didn't work...


Any idea?

For the second, could it just that with only 2 hits, it is likely that one counts 2 and the other 0 ?


In the first one, you wanted to detect the error when changing the const ? It looks as if code coverage was considering aData should always be nil.

Did you tried a print statement in the first branch, to count effectively ?

Filed bug rdar://39442631


The issue only occurs with if-else blocks inside a class (either final or non-final). Problem does not occur with if-else blocks inside the init of a struct.


Futhermore, if I employ a workaround by moving the if-else into a static class function, then all code is marked as being covered. For example:


init(x anX: Int) {
   s = IIFoo.makeProperty(withValue: anX)
}

private class func makeProperty(withValue aValue: Int) {
    let theProperty : String

    if (aValue % 2) == 0 {
        theProperty = "even"
    } else {
        theProperty = "odd"
    }
    return theProperty
}

No, it's a bug (see separate post). The unit test code hits every line and I proved that with the debugger.

FYI: Apple marked my bug as a duplicate of rdar://39460313

Didn't know about that setting, but just tried it (set all targets to YES for "Generate Legacy Test Coverage Files"). Same exact outcome as when set to NO, unfortunately.

It is interseting to note that they mark your bug as duplicate to a more recent bug report !