由于 Apple 提供了 Xcode 9.3 xccov
,所以这里有一个使用它的解决方案,它不依赖第三方依赖项(并且不关心您是否使用xcpretty
等-quiet
)
概述xccovreport
和xccov
当您的 Scheme 启用了测试覆盖率时(或当您传递-enableCodeCoverage YES
到时xcodebuild
),将.xccovreport
创建一个文件。它包含您可以在 Xcode UI 中看到的覆盖率百分比。
该文件位于:
(对于 Xcode 9)
/Users/somename/Library/Developer/Xcode/DerivedData/MyApp-airjvkmhmywlmehdusimolqklzri/Logs/Test/E387E6E7-0AE8-4424-AFBA-EF9FX71A7E46.xccovreport
(对于 Xcode 10)
/Users/somename/Library/Developer/Xcode/DerivedData/MyApp-airjvkmhmywlmehdusimolqklzri/Logs/Test/Test-MyApp-2018.10.12_20-13-43-+0100.xcresult/action.xccovreport
xcodebuild
(除非您在via中指定不同的文件夹-derivedDataPath
)
注意:在 Xcode 10 中,.xccovreport
文件位置会在测试完成后在控制台中打印出来,但 Xcode 9 不会这样做。无论如何,依赖它可能不是一个好主意,因为它可能会被静音(例如 by xcpretty
)
该文件不是纯文本,要查看它,您必须调用:
xcrun xccov view <path_to_xccovreport_file>
这将输出报告。(您可以通过--json
JSON 报告)
我们需要做什么
我们希望能够解析文件并打印出总百分比(这样 GitLab 就可以选择它并在仪表板中使用它)。
有几个挑战:
- 首先我们需要找出xccovreport
包含随机字符串的文件路径(在两个地方)
- 然后我们需要解析文件(使用一些正则表达式)并提取总百分比。
剧本
这是我正在使用的(欢迎任何改进建议,因为我不是 bash 专家):
#!/bin/bash
#1
# Xcode 10
TEST_LOGS_DIR=`xcodebuild -project MyApp.xcodeproj -showBuildSettings | grep BUILD_DIR | head -1 | perl -pe 's/\s+BUILD_DIR = //' | perl -pe 's/\/Build\/Products/\/Logs\/Test/'`
TEST_RESULTS_DIR=`ls -t $TEST_LOGS_DIR | grep "xcresult" | head -1`
TEST_COV_REPORT_FILENAME=`ls "$TEST_LOGS_DIR/$TEST_RESULTS_DIR/1_Test" | grep "xccovreport"`
TEST_COV_REPORT_FULL_PATH="$TEST_LOGS_DIR/$TEST_RESULTS_DIR/1_Test/$TEST_COV_REPORT_FILENAME"
# Xcode 9
# TEST_LOGS_DIR=`xcodebuild -project MyApp.xcodeproj -showBuildSettings | grep BUILD_DIR | head -1 | perl -pe 's/\s+BUILD_DIR = //' | perl -pe 's/\/Build\/Products/\/Logs\/Test/'`
# TEST_COV_REPORT_FILENAME=`ls $TEST_LOGS_DIR | grep "xccovreport"`
# TEST_COV_REPORT_FULL_PATH="$TEST_LOGS_DIR/$TEST_COV_REPORT_FILENAME"
# More general recursive search. Perhaps less likely to fail on new Xcode versions. Relies on filepaths containing timestamps that sort alphabetically correctly in time
# TEST_LOGS_DIR=`xcodebuild -project MyApp.xcodeproj -showBuildSettings | grep BUILD_DIR | head -1 | perl -pe 's/\s+BUILD_DIR = //' | perl -pe 's/\/Build\/Products/\/Logs\/Test/'`
# TEST_COV_REPORT_FULL_PATH=`find $TEST_LOGS_DIR -name '*.xccovreport' | sort -r | head -1`
#2
TOTAL_XCTEST_COVERAGE=`xcrun xccov view $TEST_COV_REPORT_FULL_PATH | grep '.app' | head -1 | perl -pe 's/.+?(\d+\.\d+%).+/\1/'`
#3
echo "TOTAL_XCTEST_COVERAGE=$TOTAL_XCTEST_COVERAGE"
它能做什么
#1
- 获取BUILD_DIR
然后操作路径以获取xccovreport
文件。注释/取消注释您的 Xcode 版本的块。
#2
- 我们以文本形式的完整报告开始。grep '.app'
只接受包含.app
. 这保证存在,因为有一行报告总覆盖率并包含MyApp.app
. 将有多个匹配项,但第一个匹配项将始终是总体 codecov 总分。所以我们使用结果head -1
的第一行grep
。
现在我们有一条如下所示的行:
MyApp.app 12.34% (8/65)
我们使用 perl 正则表达式只取“12.34%”部分。
#3
- 我们简单地打印出结果(连同变量名,以便稍后在 GitLab CI 中更容易找到)
如何使用
- 替换
MyApp.xcodeproj
为您的正确值
- 确保在步骤中应用正确的逻辑
#1
(Xcode 9 / Xcode 10 / Generalized recursive search)
- 保存到
printCodeCov.sh
项目根目录中的文件。
- 使文件可执行
chmod +x printCodeCov.sh
- 在您的
.gitlab-ci.yml
文件中,添加一行script
内容- ./printCodeCov.sh
- 在您的 GitLab 管道设置中,将测试覆盖率解析设置为
TOTAL_XCTEST_COVERAGE=(.+)%
笔记
- 这不
--json
使用xccov
. 对于该版本,请参见下文。
- 由于对文件夹位置和报告格式有多种假设,此解决方案可能很脆弱
- 我使用
perl
而不是sed
因为后者太难了(BSD/GNU 差异、正则表达式限制等)。
JSON版本
如果您更愿意使用JSON
报告(来自xccov
),那么在脚本中您需要这样的内容:
# Xcode 10
COV_NUMBER_FRACTION=`xcrun xccov view --json $TEST_COV_REPORT_FULL_PATH | perl -pe 's/.+?\.app.+?"lineCoverage":([^,]+).+/\1/'`
# Xcode 9
# COV_NUMBER_FRACTION=`xcrun xccov view --json $TEST_COV_REPORT_FULL_PATH | perl -pe 's/.+"targets"[^l]+lineCoverage":([^,]+),.+/\1/'`
COV_NUMBER_PERCENTAGE=`bc <<< $COV_NUMBER_FRACTION*100`
TOTAL_XCTEST_COVERAGE=`printf "%0.2f%%\n" $COV_NUMBER_PERCENTAGE`