安装
pip install ddt
使用
DDT包含类的装饰器ddt和两个方法装饰器data(直接输入测试数据),file_data(可以从json或者yaml中获取测试数据),只有yaml和yml结尾的文件以yaml形式上传,其他情况下默认为json,data中的数据类型包含单个值,元组,列表和字典
@data(a,b)
a和b各运行一次用例
@data([a,d],[c,d])
如果没有unpack,那么[a,b]当成一个参数传入用例运行
如果有unpack,那么[a,b]被分解开,按照用例中的两个参数传递
@file_data(filename)
对于json的文件,每一个json元素按照一个用例运行
例子
1. @data中单个数值传递
import unittest
from ddt import ddt, data, unpack
@ddt
class FooTestCase(unittest.TestCase):
@data(1, 2, 3)
def test_single(self, a):
print("\nthis is " + str(a))
if __name__ == '__main__':
unittest.main()
输出结果为
2. 列表作为@data的参数
import unittest
from ddt import ddt, data, unpack
@ddt
class FooTestCase(unittest.TestCase):
# 列表作为参数传递,并且没有添加unpack
@data([1, 2], [3, 4])
def test_list(self, a, b):
print("\na is " + str(a) + " b is " + str(b))
if __name__ == '__main__':
unittest.main()
输出结果
输出结果会报错,因为参数[1, 2]会作为一个整体传给a,而b则没有传入任何参数,所以提示缺少b这个参数,改为如下这样
import unittest
from ddt import ddt, data, unpack
@ddt
class FooTestCase(unittest.TestCase):
# 列表作为参数传递,添加unpack
@data([1, 2], [3, 4])
@unpack
def test_list(self, a, b):
print("\na is " + str(a) + " b is " + str(b))
if __name__ == '__main__':
unittest.main()
输出结果就正确了
3. 字典作为@data的参数
import unittest
from ddt import ddt, data, unpack
@ddt
class FooTestCase(unittest.TestCase):
@data({"key": "Tom", "value": 18}, {"key": "lucy", "value": 20})
def test_map(self, key1):
print("\nkey is " + str(key1))
if __name__ == '__main__':
unittest.main()
输出结果
如果没有添加@unpack,和list类似,会把map作为一个参数传入,这时函数参数的名字叫什么都无所谓。如果加入了@unpack,函数的参数的名字需要和map中key的名字一致,否则会报错
import unittest
from ddt import ddt, data, unpack
@ddt
class FooTestCase(unittest.TestCase):
@data({"name": "Tom", "age": 18}, {"name": "lucy", "age": 20})
@unpack
def test_map(self, name, age):
print("\nkey is " + name + " value is " + str(age))
if __name__ == '__main__':
unittest.main()
如上代码所示,test_map的参数名称必须叫name和age,因为data是个map类型,map中的key值分别为name和age,如果叫别的名字,程序就会报错。
4. file_data传入json文件
json文件中如果需要传入多组数据进行测试,可以写一个列表,然后列表里面包含多个json串,格式如下
[
{},
{},
{}
]
每一个子json中写入要传入的参数,每个子json串中key的值要相同,value的值根据测试需求填写
[
{
"name": "lucy",
"age": 2
},
{
"name": "tom",
"age": 10
}
]
value的值也可以为一个json串,如下para的值就是一个json串
[
{
"body": {},
"para": {
"d": 3,
"c": "10",
"e": {
"aaa": "bbb"
}
}
},
{
"body": {},
"para": {}
}
]
5. file_data传入excel文件
首先读取excel文件,返回一个列表,列表中每个元素为一个map,map中key的值为表头的值,value的值为每一行读出来的值,excel文件如下,
import xlrd
def read_cases(file_name):
book = xlrd.open_workbook(file_name)
sh = book.sheet_by_index(0)
cases = []
for rx in range(sh.nrows):
item = {}
for cx in range(sh.ncols):
if rx != 0:
item[sh.cell_value(0, cx)] = sh.cell_value(rx, cx)
if item:
cases.append(item)
return cases
利用unittest框架调用API
import unittest
import json
import requests
from ddt import ddt, data, unpack
from read_excel import read_cases
cases = read_cases("cases.xlsx")
@ddt
class TestDashboard(unittest.TestCase):
@data(*cases)
@unpack
def test_create_dashboard(self, uid, url, name, param, header, method, expect):
# print(uid, " ", url, " ", param, "", header, "", method, " ", expect)
resp = requests.post(url, json=json.loads(param), headers=json.loads(header))
print("\n", resp.json())
if __name__ == "__main__":
unittest.main()
上面的代码中有一个地方需要注意,在给@data添加从excel读出的列表时,需要给列表的前面加上星号,如果不加星号,类似
@data([{}, {}])
这种形式,这个测试只会执行一次,如果添加了星号,会把列表分解为多个元素,类似
@data({}, {})
输出结果为