­

unittest的参数化

  • 2019 年 12 月 9 日
  • 筆記

之前写了很多关于unittest单元测试框架的文章,本小节主要介绍它在参数化方面的应用,首先需要安装第三方的库parameterized,安装的命令为:pip install parameterized。安装成功后。这里主要结合具体的案例来说明它的应用和实现的具体细节 ,编写一个两个数相加的函数,然后针对该函数来设计具体的测试点,实现的代码如下:

#!/usr/bin/env python  #author:wuya  from parameterized import  parameterized,param  import unittest    def add(a,b):     return a+b    class AddTest(unittest.TestCase):     @parameterized.expand([        param(1,1,2),        param(1.0,1.0,2.0),        param('hi',' wuya','hi wuya')     ])     def test_add_cases(self,first,second,result):        self.assertEqual(add(first,second),result)    if __name__ == '__main__':      unittest.main(verbosity=2)

执行如上的代码后,显示三个测试点都测试通过,parameterized的设计思想有点和ddt相似,至少在参数化方面可以说是思想是一致的。在执行具体的测试点时候,它是对列表里面的参数进行进行循环然后依次赋值,也就是说,当循环到第一个元组的参数的时候,first其实是1,second是1,result是2,依次循环,这样就可以使用parameterized,来达到一个测试点的代码完成N个测试点的场景的测试。当然上面的不是很完善的。具体对代码打断点,来看赋值的具体过程,如下图所示:

在如上的信息中,可以看到具体循环赋值的过程。当然上面的函数还是不够完善,至少没有加异常的处理,那么需要添加异常,完善后的代码为:

#!/usr/bin/env python  #author:wuya  from parameterized import  parameterized,param  import unittest    def add(a,b):     try:        return a + b     except Exception as e:        return e.args[0]    class AddTest(unittest.TestCase):     @parameterized.expand([        param(1,1,2),        param(1.0,1.0,2.0),        param('hi',' wuya','hi wuya')     ])     def test_add_cases(self,first,second,result):        self.assertEqual(add(first,second),result)    if __name__ == '__main__':      unittest.main(verbosity=2)

再次执行代码,依然执行通过。但是我们很清晰的看到,增加异常后,在测试的场景里面并没有考虑到异常情况的测试,比如int与str相加会怎么样,这样的测试点没加,也就意味着add()函数里面的异常部分并没有被覆盖到,具体我们结合coverage来看下,coverage执行的过程具体是执行要测试的代码,然后是分析,最后是报告,执行的命令分别是:coverage run coverage report coverage html,如下图显示命令执行的执行细节:

打开对应的html报告后,可以看到异常的代码并没有被覆盖到,如下图所示

那么就需要再次完善测试点,增加对异常的测试点的考虑,完善后的代码为:

#!/usr/bin/env python  #author:wuya  from parameterized import  parameterized,param  import unittest    def add(a,b):     try:        return a + b     except Exception as e:        return e.args[0]    class AddTest(unittest.TestCase):     @parameterized.expand([        param(1, 1, 2),        param(1.0, 1.0, 2.0),        param(1, 1.0, 2.0),        param(1, 0, 1),        param('', '', ''),        param('hi ', 'wuya', 'hi wuya'),        param(0, '', "unsupported operand type(s) for +: 'int' and 'str'"),        param(1, 'hi', "unsupported operand type(s) for +: 'int' and 'str'"),        param(1.0, 'wuya', "unsupported operand type(s) for +: 'float' and 'str'"),     ])     def test_add_cases(self,first,second,result):        self.assertEqual(add(first,second),result)    if __name__ == '__main__':      unittest.main(verbosity=2)

见如上的代码,这样结合coverage以及parameterized的工具,就能够使用很简单的代码对一个函数的代码都能够覆盖到,并且使用一个测试方法就能够测试很多的测试场景。

感谢您的阅读和关注,后续文章会持续更新。如您感兴趣,也可购买本人的书籍和实战视频,谢谢!