目录

代码覆盖率

代码库的“代码覆盖率”值表示运行的单元测试覆盖了多少生产/开发代码。维护人员尽最大努力保持此百分比很高,此过程通常使用 GitHub ActionsCodecov 等工具自动化。因此,代码覆盖率成为一个很好的指标(并非总是),用来检查特定代码库是否经过充分测试和可靠。

用于计算、读取和可视化覆盖率报告的工具和库

  • pytest-cov:允许开发人员计算和可视化覆盖率值
  • Codecov:与远程存储库集成,允许开发人员查看和比较每次 CI 运行的覆盖率值
  • GitHub Actions:允许用户自动将覆盖率报告上传到 Codecov

有替代方案吗?

coverage.py 是一个流行的 Python 库,用于计算覆盖率值,但它通常与 Python 的 unittest 配合使用。另一方面,pytest-cov 旨在与 pytest 集成,无需额外的配置。此外,Coveralls 是一个替代的覆盖率平台,但我们建议使用 Codecov,因为它易于使用并且可以与 GitHub Actions 集成。

提高覆盖率值应该是我最优先考虑的事吗?

低覆盖率百分比肯定会促使您添加更多测试,但为了覆盖率而添加薄弱的测试并非明智之举。测试应该彻底测试您的代码库,并且不应该不可靠。

本地计算代码覆盖率

pytest 允许用户传递 --cov 选项来自动调用 pytest-cov,后者会生成一个 .coverage 文件,其中包含计算的覆盖率值。 --cov 选项的值应设置为您的包的名称。例如,运行以下命令来运行测试,为 vector 包生成一个 .coverage 文件 -

python -m pytest -ra --cov=vector --cov-branch tests/

--cov 选项还会在终端本身打印一个最小的覆盖率报告!有关更多选项,请查看 文档--cov-branch 选项将启用 分支覆盖率

在您的工作流程中计算代码覆盖率

您的工作流程也应该使用 --cov 选项运行测试,该选项必须设置为您的包名称。例如 -

- name: Test package
  run: python -m pytest --cov=vector tests/

这将自动调用 pytest-cov,并生成一个 .coverage 文件,然后可以使用 codecov/codecov-action 操作上传到 Codecov

配置 Codecov 并上传覆盖率报告

有趣的是,Codecov 不需要对您的项目进行任何初始配置,假设您已经使用您的 GitHub 帐户注册了该服务。 Codecov 需要您推送或上传覆盖率报告,之后它会自动为您生成一个 Codecov 项目。

Codecov 维护 codecov/codecov-action GitHub 操作,以便用户能够轻松上传覆盖率报告。以下是一个用于通过您的工作流程上传覆盖率报告的最小工作示例,这对于简单的测试套件来说应该足够了

- name: Upload coverage report
  uses: codecov/codecov-action@v4.6.0
  with:
    token: ${{ secrets.CODECOV_TOKEN }}

以上行应该添加到运行使用 --cov 选项的测试的步骤之后。有关所有可选选项,请查看 文档。您还需要指定一个 CODECOV_TOKEN 密钥。

使用 codecov.yml

还可以使用 codecov.yml 配置 Codecov 和传递到 Codecov 的覆盖率报告。 codecov.yml 应该放在 .github 文件夹中,与您的 workflows 文件夹一起。此外,Codecov 允许您直接通过 Codecov 项目的设置创建和编辑此 YAML 文件!

推荐的 .github/codecov.yml 配置

codecov:
  notify:
    after_n_builds: x
coverage:
  status:
    project:
      default:
        target: auto
        threshold: 5%
    patch:
      default:
        informational: true

其中 xCodecov 应该等待接收的上传报告数,然后再发送状态。这将确保 Codecov 检查在所有覆盖率报告上传之前不会失败。您可以控制被视为失败的级别;上述配置将 5% 的损失设置为正常,并避免补丁覆盖率报告失败(否则,仅仅更改一行未覆盖的代码可能会导致 PR 上出现“失败”报告)。如果您拥有 100% 的覆盖率,那么您可以删除覆盖率失败设置,因为您希望任何覆盖率损失都导致失败。有关所有选项,请查看 文档