ddt数据驱动
yaml安装使用
PyYaml安装
pip install PyYaml
yaml使用
导包: import yaml
yaml语法格式
它的基本语法规则如下
- 大小写敏感
- 使用缩进表示层级关系
- 缩进时可以使用Tab键,也可以使用空格
- 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
YAML 支持的数据结构有三种:
- 字典:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
- 列表:一组按次序排列的值,又称为序列(sequence) / 列表(list)
- 纯量(scalars):单个的、不可再分的值
字典
1 2 3 4
| animal: pets
hash: { name: Steve, foo: bar }
|
列表
1 2 3 4 5 6
| - Cat - Dog - Goldfish
animal: [Cat, Dog]
|
字典套列表
1 2 3 4 5 6
| name: 小明 age: 20 languages: - Java - JavaScript - Python
|
列表套字典
1 2 3 4 5 6 7
| - - Java - JavaScript - Python - name: 小明 age: 20
|
读取yaml文件
1 2 3 4 5 6 7 8 9 10 11 12
| import yaml
file = open('yml文件路径/文件名', 'r', encoding='utf-8') content = yaml.load(stream=file, Loader=yaml.FullLoader)
print(content) print(type(content))
for i in content: print(i)
file.close()
|
open() 方法用于打开一个文件,并返回文件对象,在对文件进行处理过程都需要使用到这个函数,如果该文件无法被打开,会抛出 OSError。
注意:
- 使用 open() 方法一定要保证关闭文件对象,即调用 close() 方法
- open() 函数常用形式是接收两个参数:文件名(file)和模式(mode)
1 2
| open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
|
参数说明:
- file: 必需,文件路径(相对或者绝对路径)。
- mode: 可选,文件打开模式
- buffering: 设置缓冲
- encoding: 一般使用utf8
- errors: 报错级别
- newline: 区分换行符
- closefd: 传入的file参数类型
- opener: 设置自定义开启器,开启器的返回值必须是一个打开的文件描述符。
mode参数常用有:

ddt安装和使用
ddt数据驱动安装
pip intall ddt
ddt数据驱动使用
导包:from ddt import ddt, data, unpack, file_data
ddt数据驱动介绍
DDT包含类的装饰器@ddt和两个方法装饰器@data(直接输入测试数据)和@file_data(文件路径/文件名)
@ddt:
- 类装饰器,用于TestCase的子类test方法。
@data:
@unpack:
- 额外的装饰器,自动将元组和列表解压缩为多个参数,并将字典解压缩为多个关键字参数。
@file_data:
@data和@unpack的使用
基本数据类型
1 2 3 4 5 6 7 8 9 10 11 12 13
| import unittest from ddt import ddt, data
@ddt() class Test_ddt(unittest.TestCase): @data(1, 'name') def test_01(self, value): print(value) print(type(value))
if __name__ == '__main__': unittest.main()
|

元祖或列表
1 2 3 4 5 6 7 8 9 10 11 12 13
| import unittest from ddt import ddt, data
@ddt() class Test_ddt(unittest.TestCase): @data((1, 'name'), (1, 'name')) def test_01(self, value): print(value) print(type(value))
if __name__ == '__main__': unittest.main()
|

“*形参”会把实参解析成元组
1 2 3 4 5 6 7 8 9 10 11 12 13
| import unittest from ddt import ddt, data
@ddt() class Test_ddt(unittest.TestCase): @data((1, 'name'), (1, 'name')) def test_01(self, *value): print(value) print(type(value))
if __name__ == '__main__': unittest.main()
|

“*实参”拆包元组或列表
1 2 3 4 5 6 7 8 9 10 11 12 13
| import unittest from ddt import ddt, data
@ddt() class Test_ddt(unittest.TestCase): @data(*(1, 'name'), *[2, 'age']) def test_01(self, value): print(value) print(type(value))
if __name__ == '__main__': unittest.main()
|

@unpack拆包元组或列表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import unittest from ddt import ddt, data, unpack
@ddt() class Test_ddt(unittest.TestCase): @data((1, 'name'), (2, 'name')) @unpack def test_01(self, value, name): print(value) print(name) print(type(value)) print(type(name))
if __name__ == '__main__': unittest.main()
|

@unpack和“*实参”拆包元组或列表
注意:
- @unpack在实参传递时拆包
- “*实参”在定义时拆包
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import unittest from ddt import ddt, data, unpack
@ddt() class Test_ddt(unittest.TestCase): @data(*[(1, 'name'), [2, 'age']]) @unpack def test_01(self, value, age): print(value) print(age)
if __name__ == '__main__': unittest.main()
|

字典
1 2 3 4 5 6 7 8 9 10 11 12 13
| import unittest from ddt import ddt, data
@ddt() class Test_ddt(unittest.TestCase): @data({'name': '小明', 'age': 19}, {'name': '小黑', 'age': 20}) def test_01(self, value): print(value) print(type(value))
if __name__ == '__main__': unittest.main()
|

@unpack拆包字典
注意:
- @unpack解包字典型实参后为关键字参数,形参名必须是值的键,也就是关键字
- 如果参数名和键不一致,会报异常:TypeError
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import unittest from ddt import ddt, data, unpack
@ddt() class Test_ddt(unittest.TestCase): @data({'name': '小明', 'age': 19}, {'name': '小黑', 'age': 20}) @unpack def test_01(self, name, age): print(name) print(age) print(type(name)) print(type(age))
if __name__ == '__main__': unittest.main()
|

“**形参”会把实参解析成字典
注意:
- 实参必须是关键字参数,如@unpack解包字典型实参后为关键字参数,可以在用“**形参”解析成字典
- 如果实参不符合关键字参数格式,会报异常:TypeError
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import unittest from ddt import ddt, data, unpack
@ddt() class Test_ddt(unittest.TestCase): @data({'name': '小明', 'age': 19}, {'name': '小黑', 'age': 20}) @unpack def test_01(self, **value): print(value) print(type(value))
if __name__ == '__main__': unittest.main()
|

总结:
@data(实参)的实参传递关键字参数给测试用例方法会报错,所以“**实参”拆包字典后不能作为@data()的参数
@file_data结合yaml使用
@file_data会自动拆包yaml文件的列表和字典数据
注意:
- 对于yaml文件定义的列表会自动拆包
- 对于yaml文件定义的字典会自动拆包,第一层拆包后为普通参数
- 如果列表或字典的第二层是字典,第二层还会拆包,第二层拆包成关键字参数
- 字典拆包成关键字参数,形参必须以关键字命名
函数的参数
函数的形参和实参
定义的参数称为:形参
调用实际传递的为:实参
参数传递的两种方式
位置参数:按位置顺序进行传递
关键字参数:通过关键字指定传给某个参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| def add_num(a, b): return a + b
res1 = add_num(67, 12) print(res1)
res2 = add_num(b=34, a=12, c=11) print(res2)
res3 = add_num(30, c=12, b=12) print(res3)
|
函数定义的三种形参
- 必需参数 如:def add_num(a, b, c) ,a,b,c三个参数都必须要传
- 默认参数(缺省参数) 如:def add_num(a, b, c=99) ,c是默认参数,可以传,可以不传(不传时直接使用c=99)
- 不定长参数:如:def add_num(a, b, *args, **kwargs) ,其中a和b是必需参数,*args 可以不传,也可以传多个,它接收必需参数、默认参数完之外的位置参数,以元组的形式保存,**kwargs 可以不传,也可以传多个,接收必需参数、默认参数之外的关键字参数,以字典的形式保存
1 2 3 4 5 6 7 8 9 10
| def test(a, b, c, *args, **kwargs): print("a的值", a) print("b的值", b) print("c的值", c) print("*args的值", args) print("**kwargs的值", kwargs)
va1 = test(11, 22, 33, 4, 3, 2) va2 = test(11, 5, 6, 7, g=33, k=22, f=12) print(va1, va2)
|
扩展:不定长参数可以使用*对元组(列表也可以,但一般不用)进行拆包,**可以对字典进行拆包,拆包原理如下:
1 2 3 4 5 6 7 8 9
| def func(): return 11,22,33
c1 = func() print(c1)
a,b,c =func() print(a,b,c)
|
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| def func(a, b, c): print('这是', a) print('这是', b) print('这是', c)
func(*(1, 2, 3))
print('-------分割线-------') tu = (4, 5, 6) func(*tu)
print('-------分割线-------')
dic = {'a': 88, 'b': 90, 'c': 91} func(**dic)
|
xlrd的使用
xlrd安装
pip install xlrd
xlrd使用
导入库:import xlrd
excel操作
excel读取:xlrd.open_wordbook(excel_path)
打开excel工作簿
sheet表单操作:
- table.sheets()[0] 通过索引顺序获取
- table.sheet_names() 获取所有表单名字
table.sheet_by_index(sheet_indx)
通过索引获取表单
table.sheet_by_name(sheet_name)
通过名称获取表单
单元格操作:
- sheet.cell(i,j) 返回单元格对象注:i表示行数,j表示列数(i<=nrows,j<=ncols)
sheet.cell_type(i,j)
返回单元格中的数据类型
sheet.cell_value(i,j)
返回单元格中的数据
行操作:
sheet.nrows
获取该表单中的有效行数
sheet.row_values(i, start_colx=0, end_colx=None)
返回由该行中所有单元格的数据类型组成的列表
- sheet.row_types(i, start_colx=0, end_colx=None) 返回由该行中所有单元格的数据组成的列表
列操作:
sheet.ncols
获取列表的有效列数,注:i表示第几列,不能超过总列数(i<=ncols)
sheet.col_values(i, start_rowx=0, end_rowx=None)
返回由该列中所有单元格的数据组成的列表
- sheet.col_types(i, start_rowx=0, end_rowx=None) 返回由该列中所有单元格的数据类型组成的列表
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
| import xlrd
table = xlrd.open_workbook("../data/test_data.xls")
sheet_index = table.sheet_by_index(0) sheet_name = table.sheet_by_name("Sheet1")
row_values = sheet_index.row_values(0) print(row_values) col_values = sheet_name.col_values(0) print(col_values) cell_value = sheet_index.cell_value(0, 0) print(cell_value)
rows = sheet_index.nrows print(rows) cols = sheet_name.ncols print(cols)
""" 1:str 2:int 3:date 4:boolean """ cell_type = sheet_index.cell_type(1,1) print(cell_type)
|
excel操作实战
test_data.xls:

operationexcel.py:
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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| import xlrd
class OperationExcel: def __init__(self, filename): self.table = xlrd.open_workbook(filename)
def get_data_by_index(self, index=0): sheet = self.table.sheet_by_index(index) return self._get_data_info(sheet)
def get_data_by_name(self, name): sheet = self.table.sheet_by_name(name) return self._get_data_info(sheet)
def _get_data_info(self, sheet): keys = sheet.row_values(0) rows = sheet.nrows cols = sheet.ncols data_list = [] for row in range(1, rows): values = [] for col in range(cols): value = self.read_cell(sheet, row, col) values.append(value) ziped = zip(keys, values) data_list.append(dict(ziped)) return data_list
def read_cell(self, sheet, row, col): sheet = self.table.sheet_by_index(0) cell_value = sheet.cell_value(row, col) cell_type = sheet.cell_type(row, col) if cell_type == 1: cell_value = cell_value elif cell_type == 2 and cell_value % 1 == 0: cell_value = int(cell_value) elif cell_type == 4: cell_value = True if cell_value == 1 else False return cell_value
if __name__ == '__main__': op_ex = OperationExcel("../data/test_data.xls") data_list = op_ex.get_data_by_name("Sheet1") print(data_list)
|
读取txt文件
1 2 3 4 5 6 7
| file=open("../data/test_data.txt", 'r', encoding='utf-8') userlines = file.readlines() file.close() for line in userlines: username=line.split(',')[0] password=line.split(',')[1] print(username, password)
|
读取csv文件
1 2 3 4 5 6 7 8 9
| import csv
filepath = "../data/login_data.csv" filename = open(filepath, "r") reader = csv.reader(filename) for row in reader: print("username:%s"%row[0],"password:%s"%row[1]) filename.close()
|