作者:童蒙
编辑:amethyst
养成写单元测试的习惯,可以简化代码测试和升级的工作,提高接口的稳定性,达到快速开发的目的,是每个编程人员应该了解的内容。
在生信人员编写代码完成后,常常需要进行测试。通常需要在不同维度上进行测试,可以分为:
- 流程测试:对整个流程进行测试,目的是得出整体的流程结果是不是正确的,符合生物学意义;
- 模块测试:针对特定的模块进行,比如GO、KEGG等,目的是得到这个模块结果是否有意义,是否有bug;
- 脚本测试:针对特定的脚本进行,目的是检查脚本功能是否符合预期;
- 单元测试:作为测试的最小单元,针对特定的函数或者类进行测试。
这些不同维度的测试作用各异,相互配合相互协调,这样才能保证分析的结果符合最终的预期。
今天就给大家介绍一下python比较常用的一款用来进行单元测试的包---pytest。
什么是单元测试
我们知道,脚本是由函数或者类组成的,每个函数和类就是最基本的单元,也是最基本的原子。
针对这些基本的原子进行测试,可以在出现问题的时候,迅速的定位到问题,从而提高debug的效率,节省程序猿宝贵的时间和珍贵的头发。
python里,进行单元测试的包通常有:
- Robot Framework
- Lettuce
- Behave
- UnitTest
- Pytest
今天我们就pytest进行介绍。
安装
安装很简单,使用pip或者conda,命令如下:
pip install -U pytest
conda install -c anaconda pytest
使用案例
案例1:最简单的应用
创建一个名为test_sample.py的脚本,编写一个func,然后编写一个测试函数。
# content of test_sample.py
def func(x):
return x + 1
def test_answer():
assert func(3) == 5
在当前目录运行
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-6.x.y, py-1.x.y, pluggy-0.x.y
cachedir: $PYTHON_PREFIX/.pytest_cache
rootdir: $REGENDOC_TMPDIR
collected 1 item
test_sample.py F [100%]
================================= FAILURES =================================
_______________________________ test_answer ________________________________
def test_answer():
> assert func(3) == 5
E assert 4 == 5
E + where 4 = func(3)
test_sample.py:6: AssertionError
========================= short test summary info ==========================
FAILED test_sample.py::test_answer - assert 4 == 5
============================ 1 failed in 0.12s =============================
这个 [100%] 指运行所有测试用例的总体进度。完成后,pytest会显示一个失败报告,因为 func(3) 不返 5 。
- pytest会寻找文件以test开头,模块以test开头,类以Test开头进行测试
- 可以使用assert 来进行断言,可以进行很简单的直接验证
- 也可以用Test的class,同时进行多个测试
案例2:使用pytest raise助手
assert通常会返回一个AssertionError的状态,虽然简单,但是对于某些我们想指定错误类型的时候,就显得不太明确,这时候可以用raise助手。
def myfunc():
raise ValueError("Exception 123 raised")
def test_match():
with pytest.raises(ValueError, match=r".* 123 .*"):
myfunc()
结果如下:
$ pytest
================== test session starts ==================================================
platform linux -- Python 3.7.7, pytest-5.3.5, py-1.9.0, pluggy-0.13.1
rootdir: /mnt/e/2020-me/02_wdl/pytest
plugins: subtests-0.3.2, workflow-1.4.0
collecting ...
collected 1 item
test_sample.py . [100%]
====================== 1 passed in 0.06s ===============================================
案例3 使用fixture
fixture是pytest的核心功能,也是亮点功能。使用python的语法糖,来对特定的模块进行测试。
测试函数可以通过将fixture对象命名为输入参数来接收它们。这样无需初始化,从而减少代码量。
示例如下:
import pytest
@pytest.fixture()
def tt():
a = 5
return a
def test_01(tt):
assert tt == 5
print("断言成功")
等价于
def tt():
a = 5
return a
def test_01():
assert tt() == 5
print("断言成功")
然而使用fixture,会更加地灵活,并且不需要对函数进行初始化,提高了代码的维护性。并且pytest有许多内嵌的fixture,可以很方便地进行使用,大家可以多了解一下。
结语
本文是对pytest的简单的介绍,希望大家能够多多地使用,让代码更加稳定。后续我们会继续推出其他,请继续关注哦~~
网友评论