简单介绍
ddt(date driver test),所谓数据驱动测试,简单来说就是由数据的改变从而驱动自动化测试的执行,最终引起测试结果的改变。通过使用数据驱动测试的方法,可以在需要验证多组数据测试场景中,使用外部数据源实现对输入输出与期望值的参数化,避免在测试中使用硬编码的数据,也就是测试数据和用例脚本代码分离。
ddt它其实就是一个装饰器,它会根据你传递进来的数据来决定要生成几个测试用例。
使用的意义
1.代码复用率高:一个测试逻辑只需要写一次,可以多条测试数据复用,同时提高测试脚本的编写效率。
2.异常排查效率高:根据测试数据,每条数据生成一条测试用例,用例相互分离,一条失败的情况下不会影响其他测试用例。
3.代码可维护性高:简洁明了的测试框架,利于其他同事阅读,提高代码的可维护性。
安装及导入
cmd命令行执行安装:pip install ddt
直接导入到模块:import ddt
,或导入具体的装饰器:from ddt import ddt, data, unpack
使用详解
三个要点:
- @ddt:装饰测试类
- @data:装饰测试用例
- @unpack:装饰测试用例
要使用ddt的前提是要有测试用例类,然后用@ddt去装饰测试用例类,用@data(测试数据)去装饰测试用例,如下登录接口例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
from ddt import ddt, data from common.read_excel import readexcel from common.my_logger import log @ddt # 装饰登录测试用例类,声明使用ddt class logintestcase(unittest.testcase): excel = readexcel( "cases.xlsx" , "login" ) cases = excel.read_data() @data ( * cases) # 装饰测试用例 def test_login( self , case): case_data = eval (case[ "data" ]) expected = eval (case[ "expected" ]) case_id = case[ "case_id" ] result = login_check( * case_data) response = self .http.send(url = url, method = method, json = data, headers = headers) result = response.json() try : self .assertequal(expected[ "code" ], result[ "code" ]) self .assertequal((expected[ "msg" ]), result[ "msg" ]) except assertionerror as e: log.info( "用例:{}--->执行未通过" . format (case[ "title" ])) print ( "预期结果:{}" . format (expected)) print ( "实际结果:{}" . format (result)) raise e else : log.info( "用例:{}--->执行通过" . format (case[ "title" ])) if __name__ = = '__main__' : unittest.main() |
@ddt
它做的事情其实就等同于这句代码:logintestcase = ddt(logintestcase)
,把具体的类名传给ddt,告诉ddt是这个测试用例类要使用数据驱动。
@data
做的事情就是把测试数据作为一个参数传递给测试用例,一个数据对应生成一条测试用例,如果data里面有多个数据那么就对应生成多条测试用例。如果data里放的类似是元组、列表等这样的序列类型的数据,data会把他们当成是一个整体,即一个测试数据。
如果想一次传递多个参数给测试用例,需要自行在脚本中对数据进行分解或者使用@unpack
分解数据。如上例子中的测试用例,只使用了一个参数,但这个参数case是一个字典,字典中已经包含多个数据,直接用key获取对应的值即可。@unpack
则是可以把序列类型的数据拆分为多个,以多个参数传给测试用例,但测试用例也需要定义同等数量的参数来接收。
上面例子的测试数据cases来源是使用了openpyxl来读取excel中的测试数据的,关于openpyxl可以看我这个系列的另外一篇随笔。这里直接说明cases其实就是像下面这样的一个列表:
1
2
3
4
|
cases = [{ 'case_id' : 1 , 'title' : '正常登录' , 'data' : '("test", "test1234")' , 'expected' : '{"code": 0, "msg": "登录成功"}' }, { 'case_id' : 2 , 'title' : '密码错误' , 'data' : '("test", "123")' , 'expected' : '{"code": 1, "msg": "账号或密码不正确"}' }, { 'case_id' : 3 , 'title' : '账户名错误' , 'data' : '("test11", "test1234")' , 'expected' : '{"code": 1, "msg": "账号或密码不正确"}' }] # *解包后,一个字典就是一个测试用例数据 # 如第一个字典:{'case_id': 1, 'title': '正常登录', 'data': '("test", "test1234")', 'expected': '{"code": 0, "msg": "登录成功"}'} |
通过*解包,它的数据就是3个字典,每次给测试用例传入1个字典,而这个字典里就存放了一条完整的登录接口测试用例的测试数据,包括用例id、用例标题、测试的账号密码、期望返回的结果。
小结:
- @data(a,b):a和b各运行一次用例
- @data(*(a,b):a和b各运行一次用例,使用*解包,相当于@data(a,b)
- @data([a,d],[c,d])
如果没有@unpack[a,b]、[c,d]都会被当成一个参数传入用例,即用[a,b]运行一次,用[c,d]运行一次;
如果有@unpack,[a,b]会被分解开,一次传递两个参数给用例,用例需要定义两个参数接收
@unpack可适用元组、列表或字典,但当传入的是字典时,字典的key和用例定义的参数名需要保持一致
关键代码:@file_data,传递文件(json/yaml)
扩展
关键代码:@file_data,传递文件(json/yaml)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
# 传递json """ json文件数据 { "token":123456, "actionname": "api.login", "content": { "user": "miki", "pwd": "test123" } } """ """ yaml文件 test_list: - 11 - 22 - 12 sorted_list: [ 11, 12, 22 ] """ from ddt import * @ddt # 声明使用ddt class testfile(unittest.testcase): @file_data ( 'd:/test/test.json' ) def test_json( self , json_data): print (json_data) @file_data ( 'd:/test/test.yaml' ) def test_yaml( self , yaml_data): print ( "yaml" , yaml_data) |
以上就是python 基于ddt实现数据驱动测试的详细内容,更多关于python 实现数据驱动测试的资料请关注服务器之家其它相关文章!
原文链接:https://www.cnblogs.com/miki-peng/p/14247976.html