查看原文
其他

生信人员怎么能让代码维护性更强呢?

生信阿拉丁 生信阿拉丁 2022-05-16

点击上方蓝字关注我们!



养成写单元测试的习惯,可以简化代码测试和升级的工作,提高接口的稳定性,达到快速开发的目的,是每个编程人员应该了解的内容。




在生信人员编写代码完成后,常常需要进行测试。通常需要在不同维度上进行测试,可以分为:

  • 流程测试:对整个流程进行测试,目的是得出整体的流程结果是不是正确的,符合生物学意义;

  • 模块测试:针对特定的模块进行,比如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,可以很方便地进行使用,大家可以多了解一下。

1


结语


本文是对pytest的简单的介绍,希望大家能够多多地使用,让代码更加稳定。后续我们会继续推出其他,请继续关注哦~~


参考资料

https://www.osgeo.cn/pytest


扫码关注我们

作者:童蒙

小编:amethyst

● 三分钟看懂TMT技术 之实验篇

 深入浅出介绍聚类分析

 单细胞转录组测序知识一隅


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存