1. doctest
doctest用于测试
# 文件外命令测试
# file name: foo.py
"""
My square function.
Usage:
>>> a = my_square(4)
>>> b = my_square(3)
>>> a + b
25
"""
def my_square(num):return num * num
> python3 -m doctest foo.py # 不看详情
> python3 -m doctest -v foo.py # 看详情# 文件内命令测试
# file-name: foo.py
"""
example usage:
>>> a, b = 2, 3
>>> a+b
5
"""
if __name__ == "__main__":import doctestdoctest.testmod()
> python3 foo.py -v # 或者ide中run
2. unittest
unittest
import unittestclass TestStringMethods(unittest.TestCase):def test_upper(self):self.assertEqual('foo'.upper(), 'FOO')def test_isupper(self):self.assertTrue('FOO'.isupper())self.assertFalse('Foo'.isupper())def test_split(self):s = 'hello world'self.assertEqual(s.split(), ['hello', 'world'])# check that s.split fails when the separator is not a stringwith self.assertRaises(TypeError):s.split(2)if __name__ == '__main__':unittest.main()
使用unittest进行测试,如果是需要实现上百个测试用例,把它们全部写在一个test.py文件中,文件会越来越臃肿,后期维护页麻烦。此时可以将这些用例按照测试功能进行拆分,分散到不同的测试文件中。
Python+Unittest - discover()构建不同目录下的用例
discover(start_dir,pattern='test*.py',top_level_dir=None)
找到指定目录下所有测试模块,并可递归查到子目录下的测试模块,只有匹配到文件名才能被加载。如果启动的不是顶层目录,那么顶层目录必须单独指定。
- start_dir:要测试的模块名或测试用例目录
- pattern=‘test*.py’:表示用例文件名的匹配原则。此处匹配文件名以“test”开头的“.py”类型的文件,幸好“*”表示任意多个字符
- top_level_dir=None:测试模块的顶层目录,如果没有顶层目录,默认为None
3. PyTest
pip install pytest
使用方法 pytest test_mymod_1.py
依赖assert函数
import mymathdef test_math():assert mymath.add(2, 2) == 4def test_more_math():assert mymath.add(3, 3) == 6import pytest
@pytest.fixture
def input_value():input = 39return inputdef test_divisible_by_3(input_value):assert input_value % 3 == 0def test_divisible_by_6(input_value):assert input_value % 6 == 0@pytest.mark.parametrize("num, output",[(1,11),(2,22),(3,35),(4,44)])
def test_multiplication_11(num, output):assert 11*num == outputpytest -k test_multiplication_11.py -v
test_multiplication.py::test_multiplication_11[1-11] PASSED
test_multiplication.py::test_multiplication_11[2-22] PASSED
test_multiplication.py::test_multiplication_11[3-35] FAILED
test_multiplication.py::test_multiplication_11[4-44] PASSED
============================================== FAILURES
==============================================
_________________ test_multiplication_11[3-35] __________________
num = 3, output = 35@pytest.mark.parametrize("num, output",[(1,11),(2,22),(3,35),(4,44)])def test_multiplication_11(num, output):
> assert 11*num == output
E assert (11 * 3) == 35
test_multiplication.py:5: AssertionError
============================== 1 failed, 3 passed, 8 deselected in 0.08 seconds
==============================
pytest.fixture:让一个函数为测试提供输入,测试函数必须将该函数名称名称作为输入参数。
Pytest中fixture的几种用法
pytest.mark.parametrize:简化代码重复输入
4. 装饰器logger_decor, 显示函数调用和运行信息
from logger_decor import tron@tron
def f(a, b=1, *args, **kwargs):print('a: ', a)print('b: ', b)print('args: ', args)print('kwargs:', kwargs)return a + bf(2, 3, 4, 5, c=6, d=7)
print()
f(2, c=5, d=6)
print()
f(10)
Calling f((2, 3, 4, 5), {'c': 6, 'd': 7})
a: 2
b: 3
args: (4, 5)
kwargs: {'c': 6, 'd': 7}
Finished f(5)
Elapsed time: 1.3589859008789062e-05Calling f((2,), {'c': 5, 'd': 6})
a: 2
b: 1
args: ()
kwargs: {'c': 5, 'd': 6}
Finished f(3)
Elapsed time: 5.245208740234375e-06Calling f((10,), {})
a: 10
b: 1
args: ()
kwargs: {}
Finished f(11)
Elapsed time: 4.291534423828125e-06