Diango博客--25.使用Coverage统计测试覆盖率
文章目录
- 1. 前言
- 2. 安装 Coverage
- 3. 简单配置 Coverage
- 4. 运行 Coverage
- 5. 完善 Coverage 配置
- 6. 生成 HTML 报告
- 7. 完善单元测试
1. 前言
我们完成了对 blog 应用和 comment 应用这两个核心 app 的测试。现在我们想知道的是究竟测试效果怎么样呢?测试充分吗?测试全面吗?还有没有没有测到的地方呢?
单凭肉眼观察难以回答上面的问题,接下来我们就借助 Coverage.py,从代码覆盖率的角度来检测一下我们的测试效果究竟如何。
Coverage.py (以下简称 Coverage)是 Python 测试界最为流行的一个库之一,用来统计测试覆盖率。测试覆盖率可以从一个角度衡量代码的质量,覆盖率越高,说明测试越充分,代码出现 bug 的几率也就越小。当然需要注意的是,测试覆盖率仅仅只是衡量代码质量的一个角度,即使是 100% 的覆盖率也不能说代码就是完美的,没有 bug 的。
2. 安装 Coverage
要使用 Coverage,首先当然是安装它:
$ pipenv install coverage --dev
因为只在开发时才用得到,所以使用 Pipenv 安装时加 --dev 选项将其标记为开发时的依赖库。
3. 简单配置 Coverage
Coverage 支持很多配置选项,为了方便,通常将这些配置写在名为 .coveragerc 的文件中,Coverage 运行时会从项目根目录读取这个配置文件。因此先在项目根目录创建这个文件并写入最基本的配置:
[run]
branch = True
source = .
[report]
show_missing = True
Coverage 的配置遵循 ini 文件语法。简单来说就是,[section] 代表一个配置块,用于组织相关的一组配置。例如这里 [run] 是一个配置块,[report] 是另一个配置块,两个块下都有相关的一些配置项。配置项的格式为 key = value 。这几个简单配置项的含义为:
- branch = True 是否统计条件语句的分支覆盖情况。if 条件语句中的判断通常有 True 和 False 两种情况,设置 branch = True 后,Coverage 会测量这两种情况是否都被测试到。
- source =. 指定需统计的源代码目录,这里设置为当前目录(即项目根目录)。
- show_missing = True 在生成的统计报告中显示未被测试覆盖到的代码行号。
4. 运行 Coverage
简单配置后,我们就可以来运行 Coverage 了。打开命令行,进入项目根目录,依次运行下面的命令(注意如果没有激活python shell 虚拟需使用 pipenv run 让命令在虚拟环境中执行)。
首先运行 erase 命令清除上一次的统计信息
$ pipenv run coverage erase
manage.py test 运行 django 单元测试,这是这一次用 coverage run 来运行
$ pipenv run coverage run manage.py test
生成覆盖率统计报告
$ pipenv run coverage report
覆盖率统计报告输出如下:
Name Stmts Miss Branch BrPart Cover Missing
--------------------------------------------------------------------------------------------
_credentials.py 2 2 0 0 0% 1-2
blog\__init__.py 0 0 0 0 100%
blog\admin.py 11 0 0 0 100%
blog\apps.py 4 0 0 0 100%
blog\elasticsearch2_ik_backend.py 8 0 0 0 100%
blog\feeds.py 12 0 0 0 100%
blog\migrations\0001_initial.py 7 0 0 0 100%
blog\migrations\0002_auto_20190711_1802.py 7 0 0 0 100%
blog\migrations\0003_auto_20191011_2326.py 4 0 0 0 100%
blog\migrations\0004_post_views.py 4 0 0 0 100%
blog\migrations\__init__.py 0 0 0 0 100%
blog\models.py 62 0 0 0 100%
blog\search_indexes.py 8 0 0 0 100%
blog\templatetags\__init__.py 0 0 0 0 100%
blog\templatetags\blog_extras.py 15 0 0 0 100%
blog\tests\__init__.py 0 0 0 0 100%
blog\tests\test_models.py 58 0 2 0 100%
blog\tests\test_smoke.py 4 0 0 0 100%
blog\tests\test_templatetags.py 115 0 2 0 100%
blog\tests\test_utils.py 11 0 0 0 100%
blog\tests\test_views.py 170 0 8 0 100%
blog\urls.py 4 0 0 0 100%
blog\utils.py 10 0 2 1 92% 14->16
blog\views.py 40 7 2 0 79% 64-72
blogproject\__init__.py 0 0 0 0 100%
blogproject\settings\__init__.py 0 0 0 0 100%
blogproject\settings\common.py 22 0 0 0 100%
blogproject\settings\local.py 5 0 0 0 100%
blogproject\settings\production.py 5 5 0 0 0% 1-8
blogproject\urls.py 4 0 0 0 100%
blogproject\wsgi.py 4 4 0 0 0% 10-16
comments\__init__.py 0 0 0 0 100%
comments\admin.py 6 0 0 0 100%
comments\apps.py 4 0 0 0 100%
comments\forms.py 6 0 0 0 100%
comments\migrations\0001_initial.py 7 0 0 0 100%
comments\migrations\0002_auto_20191011_2326.py 4 0 0 0 100%
comments\migrations\__init__.py 0 0 0 0 100%
comments\models.py 15 0 0 0 100%
comments\templatetags\__init__.py 0 0 0 0 100%
comments\templatetags\comments_extras.py 12 0 2 0 100%
comments\tests\__init__.py 0 0 0 0 100%
comments\tests\base.py 10 0 0 0 100%
comments\tests\test_models.py 8 0 0 0 100%
comments\tests\test_templatetags.py 57 0 6 0 100%
comments\tests\test_views.py 34 0 4 0 100%
comments\urls.py 4 0 0 0 100%
comments\views.py 17 0 2 0 100%
fabfile.py 21 21 0 0 0% 1-43
manage.py 12 2 2 1 79% 11-12, 20->exit
scripts\__init__.py 0 0 0 0 100%
scripts\fake.py 63 63 14 0 0% 1-106
--------------------------------------------------------------------------------------------
TOTAL 876 104 46 2 87%
倒数第二列是被统计文件的测试覆盖率,倒数第一列是未被覆盖的代码行号。大部分文件测试覆盖率为 100%,说明我们的测试还是比较充分的。但从报告结果中我们发现这样几个问题:
- 有一些文件其实并不需要测试,或者并非项目的核心文件(例如使用fabiric部署项目的脚本 fabfile.py,django 的 migrations 文件等),这些文件应该从统计中排除。
- Coverage 默认显示全部文件的覆盖率统计结果,如果文件比较多的话就不好查找非 100% 覆盖率的文件。毕竟我们的目标是提高代码覆盖率,因此已达 100% 覆盖的代码文件我们不再关心。我们要做的是找到非 100% 覆盖率的文件,为其添加缺失的测试。
5. 完善 Coverage 配置
可以通过添加 Coverage 配置项轻松解决上面 2 个问题。
在 [run] 配置块中增加 omit 配置项可以指定排除统计的文件。在 [report] 配置块中增加 skip_covered 配置项可以指定统计报告中不显示 100% 覆盖的文件。
这是 .coveragerc 最终配置结果,注意我们在 omit 配置项中指定忽略了一些非核心的项目文件:
[run]
branch = True
source = .
omit =_credentials.pymanage.pyblogproject/settings/*fabfile.pyscripts/fake.py*/migrations/*blogproject\wsgi.py[report]
show_missing = True
skip_covered = True
再次按照上一节所说的方式运行 Coverage,最终报告结果如下:
Name Stmts Miss Branch BrPart Cover Missing
-----------------------------------------------------------
blog\utils.py 10 0 2 1 92% 14->16
blog\views.py 40 7 2 0 79% 64-72
-----------------------------------------------------------
TOTAL 709 7 30 1 99%33 files skipped due to complete coverage.
这个报告指出我们仍有 2 个文件没有达到 100% 的覆盖率,我们要做的就是为这两个文件中未测试的代码增加单元测试,让其达到 100% 测试覆盖率。
不过在动手写测试之前,我们要搞清楚哪些代码没被测到。命令行报告的最后一列指出了未被测试代码的行号,但是这样看着不是很直观。一种体验更好的方式是生成 HTML 报告,这样我们可以直接在 HTML 报告中查看到未被测试到的具体代码。
6. 生成 HTML 报告
coverage report 命令在命令行生成统计报告,而 coverage html 则可以生成 HTML 报告。
在上一节的基础上,运行如下命令:
$ pipenv run coverage html
运行完成后项目根目录会多出一个 htmlcov 的文件夹,里面就是测试覆盖率的 HTML 报告文件。用浏览器打开里面的 index.html 文件就可以查看报告结果了:
主页和命令行的结果是一样的,不过我们可以点击文件名,进入到对这个文件更加具体的统计报告页面,例如 blog\views.py 结果如下:
绿色部分代表已覆盖的代码,红色部分代表未覆盖的代码。查看文件我们发现,blog\views.py 中未被覆盖的代码原来是 Django 博客实现简单的全文搜索 中的代码,现在我们已经将搜索替换为 Django Haystack 全文检索 了,这段代码也就不需要了,可以直接删除。
7. 完善单元测试
blog\utils.py 的报告结果则表明我们在 Django Haystack 全文检索与关键词高亮 中自定义的搜索关键词高亮器有一个 if 分支条件未被测试到:
检查 blog/tests/test_utils.py 中的测试用例,我们发现只测试了比较短的标题不被截断,也就是
if len(text_block) < self.max_length:
判断条件为 True,缺失对判断条件为 False 的测试。所以我们来构造一个新的测试用例测试标题长度超过 max_length (默认值为 200)的情况时会被截断:
class HighlighterTestCase(TestCase):def test_highlight(self):# 省略已有代码 ...highlighter = Highlighter("标题")document = "这是一个长度超过 200 的标题,应该被截断。" + "HelloDjangoTutorial" * 200self.assertTrue(highlighter.highlight(document).startswith('...<span class="highlighted">标题</span>,应该被截断。'))
再次运行 Coverage 生成报告,测试覆盖率全都 100% 了!
$ pipenv run coverage erase
$ pipenv run coverage run manage.py test
$ pipenv run coverage report
# 输出
Name Stmts Miss Branch BrPart Cover Missing
---------------------------------------------------
---------------------------------------------------
TOTAL 704 0 28 0 100%
最后提醒一点,Coverage 运行后可能会在项目目录下生成一些文件,这些文件并不需要纳入版本管理,所以将其加入 .gitignore 文件中,防止被提交到代码库:
htmlcov/
.coverage
.coverage.*
coverage.xml
*.cover
Diango博客--25.使用Coverage统计测试覆盖率相关推荐
- 自建站的博客网站添加百度统计功能统计流量
有了自己的网站后,想要知道自己网站的访问情况怎么办,有两种方法,一种是自己写代码进行ip地址获取并解析IP地址来源从而得到IP地址属地,进一步进行统计.另一种方法就是使用现有的统计工具,我这里使用的是 ...
- 为你的CSDN博客添加CNZZ流量统计功能
一.流量统计介绍 流量统计是指通过各种科学的方式,准确的纪录来访某一页面的访问者的流量信息,目前而言,必须具备可以统计. 1.简介 统计独立的访问者数量(独立用户.独立访客): 可以统计独立的IP地址 ...
- 如何给博客园添加访问统计
昨天无意中看到别人博客中有访问人数统计这一项,觉得很有意思,便度娘学习之,终成.如图(上面黑色栏): 作为一名编程小白,还是有点小开心,跟大家分享一下. 1.http://statcounter.co ...
- Diango博客--23.单元测试:测试 blog 应用
文章目录 1. 前言 2. 搭建测试环境 3. 测试模型 4. 测试视图 5. 测试模板标签 6. 测试辅助方法和类 1. 前言 我们博客功能越来越来完善了,但这也带来了一个问题,我们不敢轻易地修改已 ...
- Diango博客--17.统计各个分类和标签下的文章数
文章目录 0.思路引导 1.Model 回顾 2.数据库数据聚合 3.使用 Annotate 4.在模板中引用新增的属性 0.思路引导 在我们的博客侧边栏有分类列表和标签列表,显示博客已有的全部文章分 ...
- 博客园 cnblogs博客添加Google Analytics统计
在cnblogs的文章列表中只可以看到自己的每篇文章的页面浏览量,没有详细的统计信息.Google Analytics作为强大的统计工具,能得到几乎所有想要的统计信息,是博客不可多得的好工具,本文介绍 ...
- Diango博客--22.Django Haystack 全文检索与关键词高亮
文章目录 1. Django Haystack 简介 2. 安装 django-haystack和elasticsearch 2 3. 构建容器来运行 elasticsearch 服务 4. 配置 H ...
- Diango博客--20.开启 Django 博客的 RSS 功能
1.Rss简介 博客提供 RSS 订阅应该是标配,这样读者就可以通过一些聚合阅读工具订阅你的博客,时时查看是否有文章更新,而不必每次都跳转到博客上来查看.现在我们就来为博客添加 RSS 订阅功能. R ...
- Diango博客--15.通过 Django Pagination 实现简单分页(一)
文章目录 0.思路引导 1.Paginator 类的常用方法 2.用 Paginator 给文章列表分页 3.在模板中设置分页导航 4.效果展示 0.思路引导 1)当博客上发布的文章越来越多时,通常需 ...
最新文章
- “机器换人”没什么可抱怨
- 图像处理与计算机视觉:基础,经典以及最近发展(1)序
- Apache Spark 1.5新特性介绍
- Win10无法使用小娜搜索本地应用问题的解决方案
- SpringBoot集成Flowable_Jsite办理任务菜单报403
- JQuery UI AutoComplete 与 Strtus2 结合使用
- Rokon 关于精灵的点击事件
- paip.提升性能---list,arraylist,vector,linkedlist,map的选用..
- journalctl日志管理
- 分享一些免费的MD5解密网站
- Windows10 + Anaconda(python3.6)安装labelling
- 希捷硬盘查询保修期限的网址
- ADSL共享上网(简单方法)
- 怎么学好高中数学高一数学学习方法有哪些
- qt清空qtablew_qt项目:员工信息管理系统
- 至联云讲解《FIL和BTC的区别是什么?》
- Java 数字转中文数字(会计格式与非会计格式,暂不包含小数)
- Deferred异步操作
- 病案首页计算机管理系统功能一般不包括,病案管理系统
- 沟通的艺术与处世的智慧 读书笔记
热门文章
- 修改ubuntu的IP地址,静态IP地址
- C++基础1 数据类型 常量
- 2014年英语一作文partA
- 2014年考研英语一完型填空知识点
- 三种钱非常奥妙 花越多就赚越多
- 一网打尽中文编码转换---6种编码30个方向的转换
- 最新ffmpeg编译和用eclipse进行源码调试
- 解决:org.apache.rocketmq.client.exception.MQClientException: No route info of this topic, TopicTest
- Oracle 的 SQL语句中 decode()函数
- POI 方式-excle 表格导出实现-java-poi