Python和单元测试那些事儿

我们来说说目前几个和测试有关的东西(全程 Python 3)。

Mock

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

importlogging
fromunittest.mockimportMock
logging.basicConfig(level=logging.DEBUG)
#code
classASpecificException(Exception):
pass
deffoo():
pass
defbar():
try:
logging.info("enterfunction<foo>now")
foo()
exceptASpecificException:
logging.exception("wecaughtaspecificexception")
#unittest
deftest_foo():
foo=Mock(side_effect=ASpecificException())#noqa
logging.info("enterfunction<bar>now")
bar()
logging.info("everythingjustbefine")
if__name__=="__main__":
test_foo()

运行一下

root@archtests:pythontest_demo.py
INFO:root:enterfunction<bar>now
INFO:root:enterfunction<foo>now
INFO:root:everythingjustbefine

一个简单的测试就这么写好了。来,跟我念,Mock 大法好呀!

doctest

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

importlogging
logging.basicConfig(level=logging.DEBUG)
deffoo():
"""AutilityfunctionthatreturnsTrue
>>>foo()
True
"""
returnTrue
if__name__=="__main__":
importdoctest
logging.debug("startoftest...")
doctest.testmod()
logging.debug("endoftest...")

测试结果

root@archtests:pythontest_demo.py
DEBUG:root:startoftest...
DEBUG:root:endoftest...

unittest

这个文档确实有点长,我感觉还是仔细去读一下文档比较好。

importunittest
classTestStringMethods(unittest.TestCase):
defsetUp(self):
self.alist=[]
deftearDown(self):
print(self.alist)
deftest_list(self):
foriinrange(5):
self.alist.append(i)
if__name__=='__main__':
unittest.main()

输出结果

root@archtests:pythontest_demo.py
[0,1,2,3,4]
.
----------------------------------------------------------------------
Ran1testin0.001s

OK

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

pytest

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

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

root@archtests:pytest
=============================================testsessionstarts==============================================
platformlinux--Python3.5.2,pytest-3.0.5,py-1.4.31,pluggy-0.4.0
rootdir:/root/tests,inifile:
collected1items
test_afunc.py.
====================================1passedin0.03seconds=======================================================
root@archtests:

总结

编译器没给python做检查,就只有靠我们手写测试了 :(

发表回复