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)
    复制代码
  • 相关阅读:
    SpringIOC的小例子
    java中递归实现复制多级文件夹
    快速排序和几种简单排序
    Oracle面试的基本题
    多态的两个小例子
    单例模式
    内部类与匿名内部类
    C#
    C#
    C#
  • 原文地址:https://www.cnblogs.com/yoyo008/p/9436278.html
Copyright © 2011-2022 走看看