Python和单元测试那些事儿

文章介绍了单元测试的重要性,特别是在维护旧代码时的作用,以及Mock在处理不可预知因素中的应用。同时,提到了doctest作为文档和测试结合的便利性,unittest框架的基础用法,并推荐了pytest自动化测试工具。文章强调了测试虽然耗时,但对代码可靠性至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:https://www.weidianyuedu.com/

当修改了代码之后,单元测试可以保证API不会发生变化(假设原需求就不需API发生 变化)。这点可能一般情况下没什么感觉,但是当你去修改前辈留下的代码的时候, 你就会感谢他写了单元测试,最少让你知道了从功能上,这个函数是干什么的,而且 能保证你修改了函数内部实现,但是不影响函数功能。

写单元测试的时候会回想函数的作用,从而自动对函数进行回想和 review。

缺点嘛:耗费时间。单元测试和文档一样,属于非常重要,但是非常耗费时间的工作, 因为要考虑齐全,考虑到的边界条件越多,测试覆盖率越高,程序越可靠,而想这些东 西是很耗费时间精力的。

吐槽完毕,我们来说说目前我知道的几个和测试有关的东西(全程 Python 3)。

Mock
Mock是个好东西呀,遇到测试中出现的不可预知的或者不稳定因素,就用 Mock 来代 替。例如查询数据库(当然像目前我们用的MongoDB,由于特别灵活,可以直接在代码里 把相应的collection替换掉),例如异步任务等。举个例子:

import logging
from unittest.mock import Mock
logging.basicConfig(level=logging.DEBUG)

code

class ASpecificException(Exception):
pass
def foo():
pass
def bar():
try:
logging.info(“enter function now”)
foo()
except ASpecificException:
logging.exception(“we caught a specific exception”)

unittest

def test_foo():
foo = Mock(side_effect=ASpecificException()) # noqa
logging.info(“enter function now”)
bar()
logging.info(“everything just be fine”)
if name == “main”:
test_foo()
运行一下:

root@arch tests: python test_demo.py
INFO:root:enter function now
INFO:root:enter function now
INFO:root:everything just be fine
一个简单的测试就这么写好了。来,跟我念,Mock 大法好呀!

doctest
doctest属于比较简单的测试,写在 docstring 里,这样既能测试用,又能当文档 示例,是在是好用之极啊。缺点是,如果测试太复杂,doctest就显得太臃肿了(例如 如果测试之前要导入一堆东西)。举个例子:

import logging
logging.basicConfig(level=logging.DEBUG)
def foo():
“”“A utility function that returns True
>>> foo()
True
“””
return True
if name == “main”:
import doctest
logging.debug(“start of test…”)
doctest.testmod()
logging.debug(“end of test…”)
测试结果:

root@arch tests: python test_demo.py
DEBUG:root:start of test…
DEBUG:root:end of test…
unittest
这个文档确实有点长,我感觉还是仔细去读一下文档比较好(虽然我也没读完)。https://www.weidianyuedu.com/

import unittest
class TestStringMethods(unittest.TestCase):
def setUp(self):
self.alist = []
def tearDown(self):
print(self.alist)
def test_list(self):
for i in range(5):
self.alist.append(i)
if name == ‘main’:
unittest.main()
root@arch tests: python test_demo.py
[0, 1, 2, 3, 4]
.

Ran 1 test in 0.001s

OK

unittest框架配合上Mock,单元测试基本无忧啦。

pytest
上面的单元测试跑起来比较麻烦,当然也可以写一个脚本遍历所有的单元测试文件,然 后执行。不过 pytest 对unittest有比较好的支持。

pytest默认支持的是 函数 风格的测试,但是我们可以不用这一块嘛(而且很多时候 还是很有用的)。走进项目根目录,输入 pytest 就可以啦。它会自动发现 test_ 开头的文件,然后执行其中 test_ 开头的函数和 unittest 的 test_ 开头的 方法。

root@arch tests: pytest
========================================================= test session starts =========================================================
platform linux – Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0
rootdir: /root/tests, inifile:
collected 1 items
test_afunc.py .
====================================================== 1 passed in 0.03 seconds =======================================================
root@arch tests:
总结
编译器没给python做检查,就只有靠我们手写测试了 😦

另外其实 pytest 和 unittest 都有很多强大的特性,例如 fixture(不知道 咋翻译好),例如 skip 掉某一部分测试。当然我也是知之甚少,所以还是看文档吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值