心若磐石|Python 中如何实现参数化测试?( 二 )


在上述例子中 , ddt 库使用了三个装饰器(@ddt、@data、@unpack) , 实在是很丑陋 。 下面看看相对更好用的 parameterized 库:
import unittestfrom parameterized import parameterizedclass MyTest(unittest.TestCase):@parameterized.expand([(3,1), (-1,0), (1.5,1.0)])def test_values(self, first, second):self.assertTrue(first > second)unittest.main(verbosity=2)测试结果如下:
test_values_0 (__main__.MyTest) ... oktest_values_1 (__main__.MyTest) ... FAILtest_values_2 (__main__.MyTest) ... ok=========================================FAIL: test_values_1 (__main__.MyTest)-----------------------------------------Traceback (most recent call last):File "C:\Python36\lib\site-packages\parameterized\parameterized.py", line 518, in standalone_funcreturn func(*(a + p.args), **p.kwargs)File "C:/Users/pythoncat/PycharmProjects/study/testparam.py", line 7, in test_valuesself.assertTrue(first > second)AssertionError: False is not true----------------------------------------Ran 3 tests in 0.000sFAILED (failures=1)这个库只用了一个装饰器 @parameterized.expand , 写法上可就清爽多了 。
同样提醒下 , 原来的测试方法已经消失了 , 取而代之的是三个新的测试方法 , 只是新方法的命名规则与 ddt 的例子不同罢了 。
介绍完 unittest , 接着看已经死翘翘了的nose以及新生的nose2 。 nose 系框架是带了插件(plugins)的 unittest , 以上的用法是相通的 。
另外 , nose2 中还提供了自带的参数化实现:
import unittestfrom nose2.tools import params@params(1, 2, 3)def test_nums(num):assert num < 4class Test(unittest.TestCase):@params((1, 2), (2, 3), (4, 5))def test_less_than(self, a, b):assert a < b最后 , 再来看下 pytest 框架 , 它这样实现参数化测试:
import pytest@pytest.mark.parametrize("first,second", [(3,1), (-1,0), (1.5,1.0)])def test_values(first, second):assert(first > second)测试结果如下:
==================== test session starts ====================platform win32 -- Python 3.6.1, pytest-5.3.1, py-1.8.0, pluggy-0.13.1rootdir: C:\Users\pythoncat\PycharmProjects\study collected 3 itemstestparam.py .Ftestparam.py:3 (test_values[-1-0])first = -1, second = 0@pytest.mark.parametrize("first,second", [(3,1), (-1,0), (1.5,1.0)])def test_values(first, second):> assert(first > second)E assert -1 > 0testparam.py:6: AssertionError. [100%]========================= FAILURES ==========================_________________________ test_values[-1-0] _________________________first = -1, second = 0@pytest.mark.parametrize("first,second", [(3,1), (-1,0), (1.5,1.0)])def test_values(first, second):> assert(first > second)E assert -1 > 0testparam.py:6: AssertionError===================== 1 failed, 2 passed in 0.08s =====================Process finished with exit code 0依然要提醒大伙注意 , pytest 也做到了由一变三 , 然而我们却看不到有新命名的方法的信息 。 这是否意味着它并没有产生新的测试方法呢?或者仅仅是把新方法的信息隐藏起来了?
4、最后小结上文中介绍了参数化测试的概念、实现思路 , 以及在三个主流的 Python 测试框架中的使用方法 。 我只用了最简单的例子 , 为的是快速科普(言多必失) 。


推荐阅读