Python 数据驱动 unittest + ddt

一数据驱动测试的含义:python

在百度百科上的解释是:
数据驱动测试,即黑盒测试(Black-box Testing),又称为功能测试,是把测试对象看做一个黑盒子。利用黑盒测试法进行动态测试时,须要测试软件产品的功能,不需测试软件产品的内部结构和处理过程。数据驱动测试注重于测试软件的功能性需求,也即数据驱动测试使软件工程师派生出执行程序全部功能需求的输入条件。数据库

在微软网站上的解释是:数组

数据驱动的单元测试是为数据源中的每一行重复运行的一种单元测试。
数据驱动的单元测试的经常使用状况是使用多个输入值测试 API。不是编写调用 API 的多个单元测试(每一个单元测试均具备一组新的输入),也不是在单元测试中建立一个数组并使用循环代码,而是能够编写执行 API 的单个单元测试方法。而后能够从数据库表的行中进行数据检索以便传递给该测试方法的连续调用。可使用此技术测试由不一样用户(每一个用户具备不一样角色)使用的应用程序。对于每一个用户,数据源中的一行将根据角色指示预期响应。而后,该测试将经过针对每一个用户运行功能,对该应用程序进行测试,并验证产生的响应是否与预期响应一致。bash

在测试工做中,针对某一API接口,或者某一个用户界面的输入框,须要设计大量相关的用例,每个用例包含实际输入的各类可能的数据。一般的作法是,将测试数据存放到一个数据文件里,而后从数据文件读取,在脚本中循环输入测试数据,并对结果进行验证。而该实现方案,按照微软网站的解释,并不属于数据驱动测试。那么什么是数据驱动测试呢?接下来咱们一块儿看一个实例,便一清二楚了。app

数据驱动测试的环境准备:框架

  • 测试框架的选择:在这里选择的是Python开发语言,测试框架使用Unittest和DDT相结合的方式。
    在python中, unittest测试框架以下:
    import unittest
    
    
    class MyTestCase(unittest.TestCase):
    
        def setUp(self):
            '''
            testcase init ...
            :return:
            '''
            print('setup')
    
        def test_sth(self):
            '''
            must use test_***
            :return:
            '''
            print('test something')
    
        def tearDown(self):
            '''
            testcase release ...
            :return:
            '''
            print('teardown')
    
    if __name__ == '__main__':
        unittest.main()
    

     

Unittest框架包含一个test Fixture,test Fixture由三部分组成,setup,testcase和teardown。Setup过程,是测试用例执行前的初始化过程,teardown过程,是在测试用例执行后,对资源进行释放与回收的过程;而testcase是具体的测试用例。单元测试

  • 引入ddt框架,须要从ddt官网安装ddt的模块。安装ddt模块后,使用测试驱动框架后,只须要如下几行代码:

      

    import unittest
    import ddt
    
    
    @ddt.ddt
    class MyTestCase(unittest.TestCase):
    
        def setUp(self):
            '''
            testcase init ...
            :return:
            '''
            print('setup')
    
        @ddt.data(['t1' ,'r1'] ,
                  ['t2' , 'r2'])
        @ddt.unpack
        def test_sth(self , testdata , expectresult):
            '''
            must use test_***
            :return:
            '''
            print('test something')
            print(colored('%s - %s'%(testdata , expectresult), 'blue'))
    
        def tearDown(self):
            '''
            testcase release ...
            :return:
            '''
            print('teardown')
            print()
    
    if __name__ == '__main__':
        unittest.main()
    

      

首先在头部导入ddt;其次在测试类前声明使用ddt(@ddt.ddt); 第三步,在测试方法前,使用@ddt.data和@unpack进行修饰。而测试数据,在data中进行填加,该demo,有两条测试数据,每条测数据有两个字段,第一个是测试数据,第二个是指望的测试结果。从代码中,能够看到,咱们在测试用例的实体中,并未使用循环。那么执行后,是什么样的效果呢?测试

setup
test something
t1 - r1
teardown

.setup
test something
t2 - r2
teardown

.
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

  

能够看到,测试结果有两条测试用例被执行,而非一条测试用例。也就是测试框架,自动将测试数据分在两条测试用例里来执行。经过调试的print语句,咱们也能够看到,两条用例执行时的输出状况。网站

数据驱动测试的实例:ui

上述,咱们对数据驱动的使用进行了介绍,接下来,咱们一块儿来看一下在工做中是如何应用的。目前数据驱动,被用在了搜索app的自动化测试执行过程当中。应用的场景是,测试时须要在app里打开不一样的垂搜,并验证对应的垂搜页面被正常打开,此时须要传入两个字段,一是垂搜的名称,二是打开垂搜后,页面里的特殊标识,在此,咱们选择的是HTML5页面中的xpath。具体的代码示例以下:

在未使用数据驱动框架以前,测试这个场景时,每一个垂搜单独实现了一条测试用例,这里面有18个垂搜,所以以前对应的是18条测试用例,可见重复的代码量很高。在使用数据驱动框架后,只须要实现一条测试用例就能够知足需求,同时须要编写的代码量很低。关于数据驱动,网上也有不少其余的解决方案,例如将测试数据写到excel中,再从excel中读取数据。而这一过程,须要编写必定的代码,使用框架后,彻底省去了这一过程。

 

import unittest
from ddt import ddt, data, unpack
import csv
from pprint import pprint


def add(a, b):
    print('*'*5 ,a, b)
    c = a + b
    print('c' ,c)
    return c

def addstr(a, b):
    c = a + b
    return c


def get_csv_data():
    value_rows = []
    with open('./mfile.csv') as f:
        f_csv = csv.reader(f)       # 忽略表头
        next(f_csv)
        for r in f_csv:
            value_rows.append([ int(i) for i in r])
    pprint(value_rows)
    return value_rows

def write_csv_data():
    pass

@ddt
class Test(unittest.TestCase):
    @data((1, 1, 2), (1, 2, 3))
    @unpack
    def test_addnum(self, a, b, expected_value):
        self.assertEqual(add(a, b), expected_value)

    @data(*get_csv_data())
    @unpack
    def test_addstr(self, a, b, expected_value):
        self.assertEqual(add(a, b), expected_value)


if __name__ == "__main__":
    suite = unittest.TestLoader().loadTestsFromTestCase(Test)
    unittest.TextTestRunner(verbosity=2).run(suite)

  

 

 
使用数据驱动框架的意义:

- 代码复用率高。同一测试逻辑编写一次,能够被多条测试数据复用,提升了测试代码的复用率,同时能够提升测试脚本的编写效率。- 异常排查效率高。测试框架依据测试数据,每条数据生成一条测试用例,用例执行过程相互隔离,在其中一条失败的状况下,不会影响其余的测试用例。- 代码的可维护性高。清晰的测试框架,利于其余测试工程师阅读,提升了代码的可维护性。

相关文章
相关标签/搜索