12

我有一个由 Swift 3.0 和 CocoaPods 编写的 iOS 项目。我已经为这个项目配置了 Gitlab CI,它运行良好。这是我的 .gitlab-ci.yml 文件:

stages:
- build
build_project:
  stage: build
  script:
  - rm -rf Pods;rm -rf MyProject.xcworkspace;rm -rf MyProject.xcodeproj/project.xcworkspace
  - pod install
  - xcodebuild clean -workspace MyProject.xcworkspace -scheme MyProject | xcpretty
  - xcodebuild test -workspace MyProject.xcworkspace -scheme MyProject -destination 'platform=iOS Simulator,name=iPhone 7,OS=10.2' | xcpretty -s
tags:
- ios
- lunchdot

我在我的 Gitlab 存储库中看不到这个项目的代码覆盖率。目前,我所有构建的覆盖率列都是空的。我尝试在CI/CD Pipelines Gitlab 设置中设置测试覆盖解析,但它没有任何效果,因为我不知道 Swift 的正则表达式。是否可以在 Gitlab CI 中为 Swift 项目设置代码覆盖率?我怎样才能做到这一点?

4

2 回答 2

13

所以,我尝试了一百万种方法来做这件事,结果问题是xcpretty。删除它后,我开始使用我的 gitlab ci 覆盖数据获得一致的结果。如果您仍然不想获得大量您不关心的数据,您可以在您的 gitlab yams 文件中使用-quiet 。不过我会发布所有内容,所以请继续阅读。

仍然需要一个用于覆盖分析的外部工具 - xcov似乎不再可用,所以我使用了slather。像魅力一样工作。

这些是步骤:

1)得到厚厚的。

2) 理顺你的 .slather.yml 文件。我的看起来如下(YourApp 显然是您的应用程序的名称):

# .slather.yml

coverage_service: cobertura_xml
xcodeproj: ./YourApp.xcodeproj
workspace: ./YourApp.xcworkspace
scheme: YourApp
source_directory: ./YourApp
output_directory: path/to/xml_report
ignore:
- "**/Pods/*"
- "thirdparty/*"
- "./Scripts/*"
- "**/3rdParty/*"
- "../**/Developer/*"
- "**/libraries/*"
- "Module-Core/*"
- "Module-Components/*"
- "**/AppUnitTests/*"

您可以在 codecov.io 等中以 html、xml 格式获取测试输出,完全由您决定。查看 slather GitHub 页面以查看可能的方法。但是对于当前的问题,我们所需要的只是在命令行中进行大量报告,以便 gitlab 可以获取它。这就是正确设置 gitlab yaml 文件的地方。

3) 设置 .gitlab-ci.yml 文件。我的看起来像这样:

stages:
  - build

build_project_1:
  stage: build
  script:
    - xcodebuild clean -workspace YourApp.xcworkspace -scheme YourApp -quiet
    - xcodebuild test -workspace YourApp.xcworkspace -scheme YourApp -destination 'platform=iOS Simulator,name=iPhone 6,OS=10.3.1' -enableCodeCoverage YES -quiet
  after_script:
    - slather coverage -s

  only:
    - master

4) 下一步是:

  • 转到您的gitlab 页面/个人资料或您所称的任何内容

  • 转到设置,然后转到管道

设置/管道

  • 向下滚动到Test coverage parsing并在此处添加此正则表达式:\d+\%\s*$

在提供的空间中添加您的正则表达式,然后保存

就是这样。您需要做的就是调用构建。

于 2017-07-19T16:18:17.883 回答
10

由于 Apple 提供了 Xcode 9.3 xccov,所以这里有一个使用它的解决方案,它不依赖第三方依赖项(并且不关心您是否使用xcpretty-quiet

概述xccovreportxccov

当您的 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>

这将输出报告。(您可以通过--jsonJSON 报告)

我们需要做什么

我们希望能够解析文件并打印出总百分比(这样 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`
于 2018-10-12T16:25:05.730 回答