zoukankan      html  css  js  c++  java
  • 【转】Python unittest数据驱动工具:DDT

    背景

    python 的unittest 没有自带数据驱动功能。

    所以如果使用unittest,同时又想使用数据驱动,那么就可以使用DDT来完成。

    DDT是 “Data-Driven Tests”的缩写。

    资料:http://ddt.readthedocs.io/en/latest/

    使用方法

    dd.ddt:

    装饰类,也就是继承自TestCase的类。

    ddt.data:

    装饰测试方法。参数是一系列的值。

    ddt.file_data:

    装饰测试方法。参数是文件名。文件可以是json 或者 yaml类型。

    注意,如果文件以”.yml”或者”.yaml”结尾,ddt会作为yaml类型处理,其他所有文件都会作为json文件处理。

    如果文件中是列表,每个列表的值会作为测试用例参数,同时作为测试用例方法名后缀显示。

    如果文件中是字典,字典的key会作为测试用例方法的后缀显示,字典的值会作为测试用例参数。

    ddt.unpack:

    传递的是复杂的数据结构时使用。比如使用元组或者列表,添加unpack之后,ddt会自动把元组或者列表对应到多个参数上。字典也可以这样处理。参见下面的示例2.

    测试用例方法名生成规则

    使用ddt后,会产生一个新的测试用例方法名:之前的测试用例方法名_ordinal_data

    之前的测试用例方法名:即定义的测试用例方法名。比如def test_large(),这里就是test_large

    ordinal:整数,从1开始递加。

    data:如果传递过来的数据存在__name__属性,则这里就是该数据的__name__值。如果未定义__name__属性,ddt会尽量将传递过来的数据转化为python标识符,作为data显示。比如(3,2)就转化为3_2。需要注意的是,如果数据是字典,则这里就是字典的key。

    使用示例

    1. data直接放入数值

    需要导入ddt包,然后再TestCase类上采用@ddt进行装饰,测试方法上装饰@data()。

    data可以是数值,也可以是字符串。

    复制代码
    import unittest
    from ddt import ddt, data
    from ddt_demo.mycode import larger_than_two
    
    @ddt
    class FooTestCase(unittest.TestCase):
        
        @data(3, 4, 12, 23)
        def test_larger_than_two(self, value):
            self.assertTrue(larger_than_two(value))
    
        @data(1, -3, 2, 0)
        def test_not_larger_than_two(self, value):
            self.assertFalse(larger_than_two(value))
    
        @data(u'ascii', u'non-ascii-N{SNOWMAN}')
        def test_unicode(self, value):
            self.assertIn(value, (u'ascii', u'non-ascii-N{SNOWMAN}'))
            
    if __name__=='__main__':
        unittest.main(verbosity=2)
    复制代码

    输出如下:

    复制代码
    test_larger_than_two_1_3 (__main__.FooTestCase) ... ok
    test_larger_than_two_2_4 (__main__.FooTestCase) ... ok
    test_larger_than_two_3_12 (__main__.FooTestCase) ... ok
    test_larger_than_two_4_23 (__main__.FooTestCase) ... ok
    test_not_larger_than_two_1_1 (__main__.FooTestCase) ... ok
    test_not_larger_than_two_2__3 (__main__.FooTestCase) ... ok
    test_not_larger_than_two_3_2 (__main__.FooTestCase) ... ok
    test_not_larger_than_two_4_0 (__main__.FooTestCase) ... ok
    test_unicode_1_ascii (__main__.FooTestCase) ... ok
    test_unicode_2_non_ascii__ (__main__.FooTestCase) ... ok
    
    ----------------------------------------------------------------------
    Ran 10 tests in 0.001s
    
    OK
    复制代码

    可以看到上面只写了3个测试方法,但是最后run了10个用例。

    这里测试方法后会被ddt加一个后缀,ddt会尝试把测试数据转化为后缀附在测试方法后,组成一个新的名字。

    2. data放入复杂的数据结构

    使用复杂的数据结构时,需要用到@unpack,同时测试方法的参数需要使用对应的多个,比如下面的frist_value 以及 second_value。

    复制代码
    import unittest
    from ddt import ddt, data,unpack
    
    @ddt
    class FooTestCase(unittest.TestCase):
    
        @data((3, 2), (4, 3), (5, 3))
        @unpack
        def test_tuples_extracted_into_arguments(self, first_value, second_value):
            self.assertTrue(first_value > second_value)
    
        @data([3, 2], [4, 3], [5, 3])
        @unpack
        def test_list_extracted_into_arguments(self, first_value, second_value):
            self.assertTrue(first_value > second_value)
    
        @unpack
        @data({'first': 1, 'second': 3, 'third': 2},
              {'first': 4, 'second': 6, 'third': 5})
        def test_dicts_extracted_into_kwargs(self, first, second, third):
            self.assertTrue(first < third < second)
            
    if __name__=='__main__':
        unittest.main(verbosity=2)
    复制代码

    执行之后,全部pass。

    3. 使用json文件

    新建文件 test_data_list.json:

    [
        "Hello",
        "Goodbye"
    ]

    新建文件  test_data_dict.json:

    {
        "unsorted_list": [ 10, 12, 15 ],
        "sorted_list": [ 15, 12, 50 ]
    }

    新建测试脚本ddt_test.py:

    复制代码
    import unittest
    from ddt import ddt, file_data
    from ddt_demo.mycode import has_three_elements,is_a_greeting
    
    @ddt
    class FooTestCase(unittest.TestCase):
    
        @file_data('test_data_dict.json')
        def test_file_data_json_dict(self, value):
            self.assertTrue(has_three_elements(value))
    
        @file_data('test_data_list.json')
        def test_file_data_json_list(self, value):
            self.assertTrue(is_a_greeting(value))
            
    if __name__=='__main__':
        unittest.main(verbosity=2)
    复制代码

    4. 使用yaml文件

    yaml或yml后缀格式的文件也是一种xml文件,有自己的格式

    注意:key 和 value 之间要有空格 ,如下:

    执行结果为:

    {'databases': 'test:192.168.1.2 dev:192.168.1.3 pre:192.168.1.5', 'username': 'localhost', 'port': 3306, 'tester': ['百花齐放', '百家争鸣', '百鸟朝凤'], 'password': 123456}

    如果是多个测试用例的数据,yaml填写格式如下:

    -
    'casenme' : '正常登陆'
    'user' : 1234
    'passwd' : 1234
    'imagcode' : 1234
    'expect_value' : 2
    -
    'casenme' : '密码错误'
    'user' : 1234
    'passwd' : 123
    'imagcode' : 1234
    'expect_value' : 2

     

    新建测试脚本ddt_test.py:

    复制代码
    import unittest
    from ddt import ddt, file_data
    from ddt_demo.mycode import has_three_elements,is_a_greeting
    
    @ddt
    class FooTestCase(unittest.TestCase):
    
        @file_data('test_data_dict.yaml')
        def test_file_data_yaml_dict(self, value):
            self.assertTrue(has_three_elements(value))
    
        @file_data('test_data_list.yaml')
        def test_file_data_yaml_list(self, value):
            self.assertTrue(is_a_greeting(value))
            
    if __name__=='__main__':
        unittest.main(verbosity=2)
    复制代码
  • 相关阅读:
    PAT 1010. 一元多项式求导 (25)
    PAT 1009. 说反话 (20) JAVA
    PAT 1009. 说反话 (20)
    PAT 1007. 素数对猜想 (20)
    POJ 2752 Seek the Name, Seek the Fame KMP
    POJ 2406 Power Strings KMP
    ZOJ3811 Untrusted Patrol
    Codeforces Round #265 (Div. 2) 题解
    Topcoder SRM632 DIV2 解题报告
    Topcoder SRM631 DIV2 解题报告
  • 原文地址:https://www.cnblogs.com/yoyo008/p/9436278.html
Copyright © 2011-2022 走看看