如何在.gitlab-ci.yml中为并行测试生成统一覆盖率报告
问题
我的.gitlab-ci.yml文件里有多个测试脚本,示例如下:
.run_warehouse_tests: &run_warehouse_tests | echo "Running tests for Warehouse" python -m pytest --durations=0 ./src/unittest -m warehouse --junitxml="junit-test-result-warehouse.xml" -v python -m pytest ./src/unittest --cov-report xml --cov=./src/main coverage lcov .run_logistics_tests: &run_logistics_tests | echo "Running tests for Logistics" python -m pytest --durations=0 ./src/unittest -m logistics --junitxml="junit-test-logistics.xml" -v python -m pytest ./src/unittest --cov-report xml --cov=./src/main coverage lcov .run_packaging_tests: &run_packaging_tests | echo "Running tests for Packaging" python -m pytest --durations=0 ./src/unittest -m packaging --junitxml="junit-test-packaging.xml" -v python -m pytest ./src/unittest --cov-report xml --cov=./src/main coverage lcov
我有两个疑问:
- 能不能生成覆盖所有测试的单一覆盖率报告?或者生成多份报告后合并成一份?
- 如果上面的需求没法实现,能不能不运行测试只生成覆盖率?我试过执行下面的命令,但它会先跑所有测试再生成报告:
python -m pytest --durations=0 ./src/unittest --cov-report xml --cov=./src/main coverage lcov
我对覆盖率生成机制不太清楚,推测可能没法直接跳过测试生成覆盖率。
解答
一、生成覆盖所有测试的单一覆盖率报告
完全可以实现,而且你的现有脚本存在重复执行全量测试的冗余问题——每个测试阶段都额外跑了一次全量测试来生成覆盖率,完全没必要。优化方案如下:
方法:分阶段收集覆盖率数据,最后合并生成报告
修改每个测试脚本,在执行对应标记的测试时就收集覆盖率数据,并通过--cov-append参数将数据追加到同一个覆盖率数据库中;最后单独加一个CI任务,基于收集到的所有数据生成最终的合并报告。
修改后的.gitlab-ci.yml示例:
# 定义通用测试模板,每个任务只跑自己的标记测试,同时收集覆盖率 .run_tests_template: &run_tests_template | echo "Running tests for $TEST_MODULE" python -m pytest --durations=0 ./src/unittest -m $TEST_TAG \ --junitxml="junit-test-result-$TEST_MODULE.xml" -v \ --cov=./src/main --cov-append --cov-report=term-missing # 仓库测试任务 warehouse_tests: stage: test variables: TEST_MODULE: Warehouse TEST_TAG: warehouse script: *run_tests_template # 物流测试任务 logistics_tests: stage: test variables: TEST_MODULE: Logistics TEST_TAG: logistics script: *run_tests_template # 包装测试任务 packaging_tests: stage: test variables: TEST_MODULE: Packaging TEST_TAG: packaging script: *run_tests_template # 新增:生成合并覆盖率报告的任务 generate_coverage_report: stage: post_test # 依赖前面三个测试任务,确保能拿到覆盖率数据文件 dependencies: - warehouse_tests - logistics_tests - packaging_tests script: # 不运行测试,直接基于已收集的.coverage文件生成xml和lcov报告 python -m pytest --cov=./src/main --cov-report=xml --cov-report=lcov --no-tests # 或者用coverage命令直接生成: # coverage xml # coverage lcov
关键说明:
--cov-append:确保每个测试任务的覆盖率数据追加到默认的.coverage二进制文件中,而不是覆盖它;--no-tests:pytest-cov提供的参数,告诉pytest不要运行测试,直接基于已有的覆盖率数据生成报告;- 优化后的脚本避免了重复跑全量测试,大幅节省CI时间。
二、能否不运行测试仅生成覆盖率?
首先明确:覆盖率数据是测试运行时追踪代码执行情况得到的,没有执行过测试就没有覆盖率数据,自然无法凭空生成报告。
但如果已经有了之前测试运行生成的.coverage数据文件(或者其他格式的覆盖率数据文件),那么可以直接基于这些文件生成各种格式的报告,不需要重新运行测试:
- 用pytest-cov:
python -m pytest --cov=./src/main --cov-report=xml --no-tests - 用coverage命令:
coverage xml、coverage lcov(默认读取.coverage文件)
所以你的推测是对的:不能跳过测试直接生成覆盖率,但如果已经有了测试留下的覆盖率数据文件,可以跳过测试步骤直接生成报告。
内容的提问来源于stack exchange,提问作者dm159dmm
相关产品推荐
相关产品推荐

