最近发现之前开源个人自用的django-ninja脚手架项目,居然有了 30 个 star。
在这个项目上增加一些新的功能时,每次修改代码后,手动测试是挺麻烦的。
并且也不知道是否会影响到以前的功能,代码覆盖率是多少。
因此决定加强该项目的单元测试,目标是 100% 覆盖核心代码。
单元测试框架就直接用 django 自带的 TestClient,没有额外使用 pytest。
之前有看过 pytest-django,但暂时用不到,就先放着。
覆盖率统计直接参考 httprunner,使用了 coverage
下面开始实操
使用 github 登录
https://app.codecov.io/
登录后,就能看到 github 账号下所有的仓库了
点击需要配置的项目后面的 Configure
然后复制 CODECOV_TOKEN 对应的值,也就是打马赛克的部分
然后取到 github 对应的仓库,创建一个秘钥,这个秘钥是给接下来的 github action 用的
具体的代码在这里
https://github.com/lihuacai168/django-ninja-demo/blob/main/.github/workflows/django-test.yml
简单说一下这个 actions 的左右,跟 Jenkins 的流水线一样,steps 就是定义步骤
大概步骤就是:
在 django 中编写单元测试非常简单,只需导入 Django.test 下面的 TestCase,继承即可,详细参考
https://github.com/lihuacai168/django-ninja-demo/blob/main/employee/tests.py
执行单测
# 首次执行需要安装coverage,pip install coverage
$ coverage run --source='.' manage.py test
Found 11 test(s).
Creating test database for alias 'default'...
System check identified some issues:
.................
----------------------------------------------------------------------
Ran 11 tests in 2.574s
OK
Destroying test database for alias 'default'...
执行单测,生成 html 报告,并且在浏览器打开
coverage run --source='.' manage.py test && coverage html && open htmlcov/index.html
可以看到整体的覆盖率是 96%,其他的文件都 100% 覆盖
utils/model_opertion.py 这个文件覆盖率只有 60%,点击进去之后,可以查看到具体哪里没有被覆盖
在实践中,有些文件不需要被覆盖的,可以通过这样配置
有些语句不需要覆盖率的,使用# pragma: no cover
就能标记为不需要覆盖
因为我们在前面配置好了 github action,代码推送到远程之后
单元测试会自动执行 (可在 action 中自行定义触发条件),并且报告统计出来,发送到 Codecov,非常的方便。
在尤其开源项目中,别人提交了 PR,我们就能根据单元测试的结果和覆盖率,决定是否接受他的 PR
https://github.com/lihuacai168/django-ninja-demo/pull/12
也可以通过配置,直接在 README 引用覆盖率结果,让别人一眼就能出来当前项目的代码覆盖率
在 codecov 中,覆盖率的结果都会被统计出来,并且历史记录,非常方便溯源
项目的单元测试经过整合 Github Ations + Coverage + TestClient + Codecov,测试流程也从手动走向自动化,大幅度提高了项目质量和可维护性。
目前整体 96%,只需要把 utils/model_opertion.py 的覆盖率提升上来,就能完美实现 100% 覆盖率,加油!