XCode 5.1对使用块的文件进行单元测试覆盖率分析失败

25
今天我的任务是为我们的代码库添加单元测试覆盖率分析。今天也是iOS 7.1与XCode 5.1发布的日子。从发布说明中可以看到:
“用于代码覆盖率测试的gcov工具已被重新实现。新版本使用LLVM项目中的llvm-cov工具。对于所有重要功能,它在功能上等同于旧版本。gcov在Xcode中的位置也已经移动,使用xcrun来调用它。如果您发现问题,请提交错误报告。对于此版本,您仍然可以使用GCC提供的旧版本gcov,即gcov-4.2。”
我在跟随几篇教程博客(这里这里这里)之后才意识到,在正确设置环境后- 在测试时在模拟器的构建文件夹中生成.gcda/.gcno 文件 - 并让报告生成工具(这里)尝试将它们解析成报告。(即一个./getcov脚本,该脚本收集您的环境变量以传递给lcov-1.10脚本以生成报告)
第一个障碍是新捆绑的gcov程序不支持使用-v参数获取版本,而这是lcov初始化的第一步。看起来似乎是个非起点,但阅读上面的发布说明后,我修改了lcov脚本以使用旧版的gcov-4.2版本,并解决了这个问题。
然而,lcov 在处理我的覆盖率数据文件时就出现了错误。这导致报告只包含了项目中按字母顺序排列的前10个文件左右,对我来说并没有什么用处。错误输出也很少且没什么帮助:

geninfo: ERROR: GCOV failed for (build_artifacts)/(class_that_errored).gcda!

我修改了lcov脚本以打印它所得到的错误(不幸的是只得到了11,在gcov(-io).c代码中找不到任何参考),并继续操作而不是退出,因此报告中留下了更多的文件,但仍有大约85%的源文件像上面那样出错。

我能够看出成功出现在报告中的文件和抛出错误的文件之间唯一的模式是任何使用内联块声明的文件都会失败。所有通过的文件都没有使用块,我检查过的所有失败的文件都包含块。奇怪。

然后我发现我可以在 CoverStory 中打开单独的 .gcda 文件,包括那些在 lcov 脚本中出错的文件。在覆盖率报告下方的消息窗口中,所有出错的文件都会显示警告信息:

(class_that_errored).gcno:no lines for '__copy_helper_block_'

(class_that_errored).gcno:no lines for '__destroy_helper_block_'

我目前最好的假设是,新的 XCode 5.1 生成的 .gcda 文件与旧的 gcov-4.2 程序无法处理块声明相关的问题。
但是我已经尝试了我能想到的一切,所以我来这里问问是否有人知道我错过的知识,或者有任何想法来进一步调试。如果有人成功地使用今天的 XCode 5.1 更新和新的 gcov 测量测试覆盖率,我也很想听听您所做的任何更改。

我正在使用gcovr(可在此处获取:https://pypi.python.org/pypi/gcovr)来解释覆盖结果,但它得到的答案比CoverStory得到的更不准确。它无法处理的GCDA文件会生成一个错误:“MySourceFile.m:没有这样的文件或目录”。奇怪的是,在有问题的GCDA文件上直接调用gcov似乎可以创建适当的文件。如果有人能够对此提供任何见解,请在下面创建一个答案! - David Doyle
此外,函数度量——而不是源代码/行度量——似乎已经消失了。在Xcode 5.1之前,lcov能够同时进行两种度量。 - Endersstocker
@Endersstocker 不确定为什么会发生这种变化,但如果您明确指示lcov使用--derive-func-data参数来派生数据,则可以恢复原始行为。我只是在Jon Reid的getcov shell脚本中的gather_coverage()函数中添加了该参数。 - jstevenco
@David-Doyle,实际上,我的评论是针对@Endersstocker关于函数测量不起作用的观察。不确定块问题出在哪里,但在我的有限评估中,我正在获取包括块的类/方法覆盖范围(例如,我正在使用带有成功/失败完成块的AFNetworking 2.0)。有关问题块内容的任何明显模式吗? - jstevenco
我正在调查一个问题,即由gcovr生成的覆盖率报告中所有包含块的文件都丢失了,当偶然发现了这个问题。我拼命尝试使用Xcode 6 beta 3构建...问题似乎已经解决了! 升级到Xcode beta对我来说不是一个选择,但至少我知道它将在未来的Xcode版本中得到修复! - Lysann Schlegel
显示剩余10条评论
4个回答

13
问题在于 LCOV 1.10 的 geninfo 脚本。它会测试 gcov 的当前版本,方法是解析版本字符串。由于 gcov 现在指向 llvm-cov,因此版本字符串被解析错误。
解决方案是修改 geninfo 中的 get_gcov_version() 子程序。在第 1868 行中,将 -v 更改为 --version。然后用以下代码替换第 1874 行:
if ($version_string =~ m/LLVM/)
{
    info("Found llvm-cov\n");
    $result = 0x40201;
}
elsif ($version_string =~ /(\d+)\.(\d+)(\.(\d+))?/)

修改后的子程序应该长这样:

sub get_gcov_version()
{
    local *HANDLE;
    my $version_string;
    my $result;

    open(GCOV_PIPE, "-|", "$gcov_tool --version")
        or die("ERROR: cannot retrieve gcov version!\n");
    $version_string = <GCOV_PIPE>;
    close(GCOV_PIPE);

    $result = 0;
    if ($version_string =~ m/LLVM/)
    {
        info("Found llvm-cov\n");
        $result = 0x40201;
    }
    elsif ($version_string =~ /(\d+)\.(\d+)(\.(\d+))?/)
    {
        if (defined($4))
        {
            info("Found gcov version: $1.$2.$4\n");
            $result = $1 << 16 | $2 << 8 | $4;
        }
        else
        {
            info("Found gcov version: $1.$2\n");
            $result = $1 << 16 | $2 << 8;
        }
    }
    return ($result, $version_string);
}

注意:请确保 --gcov-tool 的值不是 gcov-4.2


@DavidDoyle:getcov会返回错误信息吗?还是你只是收到了一个空白报告? - Endersstocker
@DavidDoyle:你能告诉我它们是什么吗? - Endersstocker
内容涉及编程,为避免混淆我将其分为三部分进行发布。 - David Doyle
gcov:未知的命令行参数“-v”。请尝试:'/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/gcov -help' gcov:您是指“-a”吗? gcov:未指定足够的位置命令行参数! 必须至少指定1个位置参数:请参见:/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/gcov -help - David Doyle
4
总结一下:这似乎解决了与 lcov 相关的问题,但仍存在原始问题(任何包含块的内容都不会出现在覆盖报告中)... - David Doyle
显示剩余8条评论

2

我没有修改geninfo,而是创建了一个llvm-cov-wrapper脚本,并使用lcov的--gcov-tool命令行选项:

#!/bin/bash
# llvm-cov wrapper to make it behave more like gcov

if [ "$1" = "-v" ]; then
    echo "llvm-cov-wrapper 4.2.1"
    exit 0
else
    /usr/bin/gcov $*
fi

必须指定至少1个位置参数: - Kunal Balani

2

实际上我注意到lcov正在使用-b选项调用gcov,而gcov-4.2会在此选项下崩溃(引发分段错误)。如果我从getinfo中删除-b选项,则即使它仍然显示一些错误信息,gcov文件仍然可以生成。

这可能就是为什么coverstory仍然可以提供覆盖输出的原因。所以我猜解决方法是从lcov中删除-b选项。并且正如你建议的那样,忽略getinfo中的错误。


0

对于任何新来的人,请注意lcov-1.11已经发布。这消除了与gcov -v兼容性的问题。然而,我正在使用XCode 6.1,仍然在一些文件上出现错误。

geninfo: WARNING: /Users/XXX/MyFile.gcno: found unrecognized record format - skipping

请注意,您可以添加--ignore-errors graph以跳过这些错误,但问题并没有真正解决。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接