pytest的插件介绍:pytest-cov、pytest-pep8与pytest-flakes

pytest插件

pytest不仅是一个功能强大的测试框架,同时也是一个插件化的测试平台。 在《Installing and Using plugins — pytest documentation》页面,介绍了几种常见的pytest插件。

实际插件数,远胜于此,参考pytest Plugin Compatibility页面,这是一个比较全的不完全列表。 要查找pytest插件,可以通过classifier——Framework :: Pytest——进行条件搜索。

插件的使用方法与功效,各有千秋。 这里介绍三个最常用的插件。 它们的共同特点是,只需要配置,就可直接使用,不需要测试代码配合。

pytest-cov

pytest-cov是自动检测测试覆盖率的一个插件。 其输出结果大致如下:

-------------------- coverage: platform linux2, python 2.6.4-final-0 ---------------------
Name                 Stmts   Miss  Cover
----------------------------------------
myproj/__init__          2      0   100%
myproj/myproj          257     13    94%
myproj/feature4286      94      7    92%
----------------------------------------
TOTAL                  353     20    94%

使用时,需要在测试命令后加--cov参数,例如:

pytest --cov=myproj tests/

其中,myproj需要替换成被测试模块名。

测试覆盖率,可以说是成功、失败以外,最重要的测试数据。 100%测试覆盖率,只是完成Python项目单元测试的一个基本要求。 因此,这个插件几乎是必选的。

pytest-pep8

PEP 8 -- Style Guide for Python Code,这是Python里一个通用的代码规范。 Python是一门优雅的语言。 然而,如果连这个规范都没遵守的Python代码,根本没有优雅可言。 而pytest-pep8,就是在做pytest测试时,自动检测代码是否符合PEP 8规范的插件。

安装后,增加--pep8参数,即可执行测试。

pytest --pep8

只要有一行不符合规范的代码,就会让整个测试都失败。 有时为了过滤一些例外的文件,还需要设置pep8ignore,详见[#样例]。

pytest-flakes

这是一个基于pyflakes的插件,对Python代码做一个快速的静态代码检查。 使用方式和pytest-pep8类似,效果也十分显著。

比如,一个test_flakes.py文件,代码如下:

import os

print('Hello world!')

添加--flakes参数,执行测试:

$ pytest --flakes test_flakes.py
=============================== test session starts ================================
platform darwin -- Python 3.6.3, pytest-3.0.7, py-1.4.33, pluggy-0.4.0
rootdir: /private/tmp, inifile:
plugins: flakes-2.0.0, cov-2.4.0
collected 1 items

test_flakes.py F

===================================== FAILURES =====================================
__________________________________ pyflakes-check __________________________________
/private/tmp/test_flakes.py:1: UnusedImport
'os' imported but unused
============================= 1 failed in 0.01 seconds =============================

这样,'os' imported but unused这个错误,就被自动检查出来了。

--verbose模式下,有时可以看到有很多case被标记为SKIPPED。 这是因为pytest-flakes会记录时间戳,自动略过没有改动的文件。

样例

最后,展示一个使用了这三个插件的完整样例。

setup.py文件示例片段如下:

setup(
    ...
    tests_require=[
        'pytest',
        'pytest-cov',
        'pytest-pep8',
        'pytest-flakes',
    ],
    ...
)

这里主要是指明这些插件的安装需要。 在执行./setup.py test时,这些包会自动安装。

setup.cfg文件示例片段如下:

[tool:pytest]
addopts = --verbose
          --cov myproj
          --pep8
          --flakes
python_files = tests/*
pep8ignore = setup.py ALL
flakes-ignore = tests/* ALL
                **/__init__.py UnusedImport

其中,myproj需要替换成被测试模块名。 addopts的配置是关键,指定了会参与执行的插件。 pep8ignore是指定不需要执行pytest-pep8的文件列表,这里以setup.py举例(实战中setup.py通常不需要忽略)。

flakes-ignore是指定不需要执行pytest-flakes的文件列表。 通常测试代码都都不需要执行,因为pytest的测试代码(尤其是fixtures)不一定符合pyflakes的标准。 而__init__.py文件有时会包含不在当前文件使用的import语句,所以需要指定不检查UnusedImport

无论pep8ignore还是flakes-ignore,都可以精确指定不检查的错误类型,像UnusedImport。 具体的错误类型,可以参考测试的错误提示。

总结

插件化,使得pytest成为了一个测试平台,提供了更多的便利与可能性。 如果既有的插件无法满足需要,甚至可以根据文档《Writing plugins — pytest documentation》,定制自己的插件。 而上述三个插件,则是最常见、乃至必选的测试组件。


相关笔记