过去几个月我一直在 Gitlab 上使用 Flutter 和 TDD 管理一个项目,并使用 Gitlab CI 来监控代码质量和测试。 随着 tinsight 项目的结束,我们现在已经进行了 700 多项测试,我们的 CI 已经达到了极速。 起初我们需要 5-10 分钟来运行整个管道,现在可能需要长达 58 分钟,唯一明显的区别是测试数量。
从我们的脚本中删除 --machine 后,我注意到
flutter test --coverage
花费的时间是本地运行时的 11 倍。
本地
PS C:\Users\lr\Documents\GitHub\hive-manager> flutter test --coverage
04:04 +707: All tests passed!
GITLAB CI
$ flutter test --coverage
45:30 +707: All tests passed!
这绝对是管道的测试阶段引起的问题,因为当我查看每个作业时间时,存在明显的差异:
code_quality - 00:05:24
test - 00:48:47
coverage - 00:02:06 (82.2%)
semantic-version - 00:01:20
我有点不知道现在该做什么,因为我还有更多的测试,但 CI 在几分钟内就开始花费相当多的成本,同时我不想在其他地方重建 CI。 这只是 Gitlab CI 的限制还是这里出了问题。 我已附上下面的 .yaml
stages: # List of stages for jobs, and their order of execution
- analyze
- test
- coverage
- semantic-version
default:
image: cirrusci/flutter:latest
cache:
paths:
- /flutter/bin/cache/dart-sdk
code_quality:
stage: analyze
before_script:
- pub global activate dart_code_metrics
- export PATH="$PATH":"$HOME/.pub-cache/bin"
script:
- flutter --version
- flutter analyze
- metrics lib -r codeclimate > gl-code-quality-report.json
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_COMMIT_BRANCH == "develop" && $CI_PIPELINE_SOURCE == "push"
- if: $CI_COMMIT_BRANCH == "develop" && $CI_PIPELINE_SOURCE == "merge_request_event"
allow_failure: true
artifacts:
reports:
codequality: gl-code-quality-report.json
test: # This job runs in the test stage.
stage: test # It only starts when the job in the build stage completes successfully.
script:
- flutter test --coverage
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_COMMIT_BRANCH == "develop" && $CI_PIPELINE_SOURCE == "push"
- if: $CI_COMMIT_BRANCH == "develop" && $CI_PIPELINE_SOURCE == "merge_request_event"
coverage: # This job runs in the test stage.
stage: coverage # It only starts when the job in the build stage completes successfully.
script:
- lcov --summary coverage/lcov.info
- lcov --remove coverage/lcov.info
"lib/config/*"
"lib/application/l10n/l10n.dart"
"lib/application/l10n/**/*"
"lib/domain/repositories/*"
"lib/injection.config.dart"
"lib/presentation/routes/*"
"lib/infrastructure/repositories/firebase_injectable_module.dart"
"**/mock_*.dart"
"**/*.g.dart"
"**/*.gr.dart"
"**/*.freezed.dart"
"**/*.mocks.dart"
"**/*.config.dart"
-o coverage/clean_lcov.info
- genhtml coverage/clean_lcov.info --output=coverage
- curl -Os https://uploader.codecov.io/latest/linux/codecov
- chmod +x codecov
- ./codecov -t $CODECOV_TOKEN
- mv coverage/ public/
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_COMMIT_BRANCH == "develop" && $CI_PIPELINE_SOURCE == "push"
- if: $CI_COMMIT_BRANCH == "develop" && $CI_PIPELINE_SOURCE == "merge_request_event"
coverage: '/lines\.*: \d+\.\d+\%/'
artifacts:
paths:
- public
semantic-version:
image: node:16
stage: semantic-version
only:
refs:
- main
- develop
script:
- touch CHANGELOG.md
- npm install @semantic-release/gitlab @semantic-release/changelog
- npx semantic-release
artifacts:
paths:
- CHANGELOG.md
其他信息 查看 GitLab 的 report.xml,我还可以看到大多数测试需要大约 2 秒才能完成,但总测试只需要 135 秒。
虽然测试工作需要约 44 分钟才能完成。
我也尝试删除
--coverage
来减少时间,结果是8分30秒,但这仍然比本地所需的1分30秒多很多。
加速 Github 操作上的
flutter test
的一种方法是并行运行它们。
flutter 支持这一点,为此我们必须传递
--concurrency
参数。它的值可以是 2 之间的任何值。这将尝试使用运行程序上可用的 2 个处理器。如果跑步者动力更强,这个数字可能会更高,如 8、16、64 等。
例如现在我们使用
Large-runner-Linux
并利用 64 作为并发
jobs:
test:
name: Unit test
runs-on: Large-runner-Linux
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: ⚙️ Install lcov
run: |
sudo apt-get update || true
sudo apt-get -y install lcov
- name: Run flutter tests
run: |
flutter test --concurrency=64 --coverage
genhtml ./coverage/coverage_with_exclusion.info -o ./coverage
这将测试执行时间从 8 分钟减少到 1.5 分钟,节省了巨大的时间。
我们之前的版本使用
runs-on: ubuntu-latest
和 flutter test --concurrency=2
这已经完成了 8 分钟到 5 分钟,所以每次构建仍然节省 3 分钟。
注:我们的测试数量大约为 700 次左右。