当前位置 主页 > 服务器问题 > Linux/apache问题 >

    Python 中如何实现参数化测试的方法示例

    栏目:Linux/apache问题 时间:2019-12-11 10:51

    之前,我曾转过一个单元测试框架系列的文章,里面介绍了 unittest、nose/nose2 与 pytest 这三个最受人欢迎的 Python 测试框架。

    本文想针对测试中一种很常见的测试场景,即参数化测试,继续聊聊关于测试的话题,并尝试将这几个测试框架串联起来,做一个横向的比对,加深理解。

    1、什么是参数化测试?

    对于普通测试来说,一个测试方法只需要运行一遍,而参数化测试对于一个测试方法,可能需要传入一系列参数,然后进行多次测试。

    比如,我们要测试某个系统的登录功能,就可能要分别传入不同的用户名与密码,进行测试:使用包含非法字符的用户名、使用未注册的用户名、使用超长的用户名、使用错误的密码、使用合理的数据等等。

    参数化测试是一种“数据驱动测试”(Data-Driven Test),在同一个方法上测试不同的参数,以覆盖所有可能的预期分支的结果。它的测试数据可以与测试行为分离,被放入文件、数据库或者外部介质中,再由测试程序读取。

    2、参数化测试的实现思路?

    通常而言,一个测试方法就是一个最小的测试单元,其功能应该尽量地原子化和单一化。

    先来看看两种实现参数化测试的思路:一种是写一个测试方法,在其内部对所有测试参数进行遍历;另一种是在测试方法之外写遍历参数的逻辑,然后依次调用该测试方法。

    这两种思路都能达到测试目的,在简单业务中,没有毛病。然而,实际上它们都只有一个测试单元,在统计测试用例数情况,或者生成测试报告的时候,并不乐观。可扩展性也是个问题。

    那么,现有的测试框架是如何解决这个问题的呢?

    它们都借助了装饰器,主要的思路是:利用原测试方法(例如 test()),来生成多个新的测试方法(例如 test1()、test2()……),并将参数依次赋值给它们。

    由于测试框架们通常把一个测试单元统计为一个“test”,所以这种“由一生多”的思路相比前面的两种思路,在统计测试结果时,就具有很大的优势。

    3、参数化测试的使用方法?

    Python 标准库中的unittest 自身不支持参数化测试,为了解决这个问题,有人专门开发了两个库:一个是ddt ,一个是parameterized 。

    ddt 正好是“Data-Driven Tests”(数据驱动测试)的缩写。典型用法:

    import unittest
    from ddt import ddt,data,unpack
    
    @ddt
    class MyTest(unittest.TestCase):
      @data((3, 1), (-1, 0), (1.2, 1.0))
      @unpack
      def test_values(self, first, second):
        self.assertTrue(first > second)
    
    unittest.main(verbosity=2)
    
    

    运行的结果如下:

    test_values_1__3__1_ (__main__.MyTest) ... ok
    test_values_2___1__0_ (__main__.MyTest) ... FAIL
    test_values_3__1_2__1_0_ (__main__.MyTest) ... ok

    ==================================================
    FAIL: test_values_2___1__0_ (__main__.MyTest)
    --------------------------------------------------
    Traceback (most recent call last):
      File "C:\Python36\lib\site-packages\ddt.py", line 145, in wrapper
        return func(self, *args, **kwargs)
      File "C:/Users/pythoncat/PycharmProjects/study/testparam.py", line 9, in test_values
        self.assertTrue(first > second)
    AssertionError: False is not true

    ----------------------------------------------
    Ran 3 tests in 0.001s

    FAILED (failures=1)