for 循环内的代码覆盖率不正确

Incorrect code coverage inside of for loop

各位溢出者大家好,

我正在开发一个 Swift class,它的初始化程序包含一个 for 循环,该循环根据 init 的参数运行一定次数。不幸的是,我无法向您展示确切的代码,但它与此类似:

init(numberOfTimes: Int) {
    ...
    for index in 0..<numberOfTimes {
        // do some stuff here
        // shows 0 coverage
    }
    ...
}

我对此初始化程序进行了多次单元测试,运行 for 循环在 0 到 5 次之间。测试通过了,但代码覆盖率总是将循环的 内部 标记为未覆盖,即使它明显运行 — 我可以在循环内设置断点,并且循环中调用的每个函数都显示为已覆盖.

此外,如果我提取 for 循环的内容,代码 确实 看起来被覆盖了,class 的整体代码覆盖率增加了近 20%:

init(numberOfTimes: Int) {
    ...
    for index in 0..<numberOfTimes {
        doOne(index)
        // this part still shows 0 coverage
    }
    ...
}

private func doOne(_ index: Int) {
    // do same things here
    // shows correct coverage
}

为什么会这样?我是否没有满足 for 循环内代码覆盖率的正确标准?

我相信这可能就是您所说的错误:

https://bugs.swift.org/browse/SR-7446

Since upgrading to Xcode 9.3/Swift 4.1, I noticed that code coverage percentage dropped in several of my projects.

The bug seems to occur when I use conditional code within an initializer...

修复于:

https://github.com/apple/swift/pull/15966

This scheme of using a designated constructor for profiling purposes is a bit brittle. One concrete issue with this is that swift ends up attempting to create distinct SILProfilers for different constructors of a nominal type, and stored property initializers we want coverage for may not be emitted in the designated constructor.

A simpler idea is to store a map from nominal types to SILProfilers, and to then create a single merged profiler instance for all constructors of a nominal type.