一、DDT(数据驱动)简介

Data-Driven Tests(DDT)即数据驱动测试,可以实现不同数据运行同一个测试用例(通过数据的不同来驱动测试结果的不同)。

ddt本质其实就是装饰器,一组数据一个场景。

ddt模块包含了一个类的装饰器ddt(@ddt)和三个方法的装饰器(@data、@unpack、@file_data),其中:

@data:包含多个你想要传给测试用例的参数,可以为列表、元组、字典等;

@file_data:会从json或yaml中加载数据;

(注意,如果文件以”.yml”或者”.yaml”结尾,ddt会作为yaml类型处理,其他所有文件都会作为json文件处理。如txt文件)

@unpack:分割元素。

(需要搭配unittest测试框架使用,实现数据驱动测试)

数据驱动测试:

1、避免编写重复代码

2、数据与测试脚本分离

3、通过使用数据驱动测试,来验证多组数据测试场景

通常来说,多用于单元测试和接口测试

二、python中使用ddt传递参数
前提:需要安装ddt包

1、传递列表、字典等数据

# get_ddt.py

import unittest
from ddt import ddt, data, unpack, file_data # 声明了ddt类装饰器
@ddt
class MyddtTest(unittest.TestCase): # @data方法装饰器
# 单组元素
@data(1,2,3)
def test_01(self, value): # value用来接受data的数据
print(value) # 多组数据,未拆分
@data([1,2],[3,4])
def test_02(self, value):
print(value) # 多组数据,拆分
# @unpac拆分,相当于把数据的最外层结构去掉
@data([5,6],[7,8])
@unpack
def test_03(self, value1, value2):
print(value1, value2) # 单个列表字典,未拆分
@data([{"name": "peter", "age": 15, "addr": "chengdu"}])
def test_04(self, value):
print(value) # 多个列表字典,拆分
@data([{"name":"peter","age":16,"addr":"chengdu"},{"name":"lily","age":17,"addr":"chengdu"}])
@unpack
def test_05(self, value1, value2):
print(value1, value2) # 单个字典,拆分
# @data里的数据key必须与字典的key保持一致
@data({"name":"jack","age":20})
@unpack
def test_06(self, name, age):
print(name, age) # 多个字典, 拆分
@data({"name":"peter","age":18,"addr":"chengdu"},{"name":"lily","age":19,"addr":"chengdu"})
@unpack
def test_07(self, name, age, addr):
print(name, age, addr) # 多个列表字典,引用数据
testdata = [{"name": "peter", "age": 21, "addr": "chengdu"}, {"name": "lily", "age": 22, "addr": "chengdu"}]
@data(testdata)
@unpack
def test_08(self, value1, value2):
print(value1, value2) # @data(*testdata):*号意为解包,ddt会按逗号分隔,将数据拆分(不需要@unpack方法装饰器了)
testdata = [{"name":"peter","age":23,"addr":"chengdu"},{"name":"lily","age":24,"addr":"chengdu"}]
@data(*testdata)
def test_09(self, value):
print(value) if __name__ == "__main__":
unittest.main()
运行结果:

...................
----------------------------------------------------------------------
Ran 19 tests in 0.000s OK
1
2
3
[1, 2]
[3, 4]
5 6
7 8
[{'name': 'peter', 'age': 15, 'addr': 'chengdu'}]
{'name': 'peter', 'age': 16, 'addr': 'chengdu'} {'name': 'lily', 'age': 17, 'addr': 'chengdu'}
jack 20
peter 18 chengdu
lily 19 chengdu
{'name': 'peter', 'age': 21, 'addr': 'chengdu'} {'name': 'lily', 'age': 22, 'addr': 'chengdu'}
{'name': 'peter', 'age': 23, 'addr': 'chengdu'}
{'name': 'lily', 'age': 24, 'addr': 'chengdu'}

2、传递json、yaml文件

# config.json

{
"stu1": {
"name": "Peter",
"age": 29,
"addr": "BeiJing"
},
"stu2": {
"name": "Jack",
"age": 30,
"addr": "ShenZhen"
}
}
# config.yaml

# 使用-分隔用例,则yaml读取到的数据类型为列表
-
model: 注册模块
title: 注册成功
url: http://api.nnzhp.cn/api/user/user_reg
method: POST
data:
username: yingcr10
pwd: Ace123456
cpwd: Ace123456
check:
error_code: 0
msg: 注册成功!
-
model: 注册模块
title: 用户名长度小于6位,注册失败
url: http://api.nnzhp.cn/api/user/user_reg
method: POST
data:
username: yingc
pwd: Ace123456
cpwd: Ace123456
check:
error_code: 3002
# get_ddt.py

import unittest
from ddt import ddt, data, unpack, file_data # 声明了ddt类装饰器
@ddt
class MyddtTest(unittest.TestCase): # @file_data加载json文件
# **testdata:将提取到的数据存放在空字典testdata中
@file_data("config.json")
def test_10(self, **testdata):
# 再从字典testdata中单独提取参数
name = testdata['name']
age = testdata['age']
addr = testdata['addr']
print(testdata)
print(name, age, addr) # 直接提取参数, test()方法中的参数必须与json文件中的键保持一致
@file_data("config.json")
def test_11(self,name, age, addr):
name = name
age = age
addr = addr
print(name, age, addr) # @file_data加载yaml文件
@file_data("config.yaml")
def test_12(self, model, title, url, method, data, check):
username = data['username']
pwd = data['pwd']
cpwd = data['pwd']
print(model, title, url, method, data, check)
print(username, pwd, cpwd) # **testdata:将提取到的数据存放在空字典testdata中
@file_data("config.yaml")
def test_13(self, **testdata):
# 再从字典testdata中单独提取参数
model = testdata['model']
title = testdata['title']
print(testdata)
print(model, title) if __name__ == "__main__":
unittest.main()
运行结果:

........
----------------------------------------------------------------------
Ran 8 tests in 0.000s OK
{'name': 'Peter', 'age': 29, 'addr': 'BeiJing'}
Peter 29 BeiJing
{'name': 'Jack', 'age': 30, 'addr': 'ShenZhen'}
Jack 30 ShenZhen
Peter 29 BeiJing
Jack 30 ShenZhen
注册模块 注册成功 http://api.nnzhp.cn/api/user/user_reg POST {'username': 'yingcr10', 'pwd': 'Ace123456', 'cpwd': 'Ace123456'} {'error_code': 0, 'msg': '注册成功!'}
yingcr10 Ace123456 Ace123456
注册模块 用户名长度小于6位,注册失败 http://api.nnzhp.cn/api/user/user_reg POST {'username': 'yingc', 'pwd': 'Ace123456', 'cpwd': 'Ace123456'} {'error_code': 3002}
yingc Ace123456 Ace123456
{'model': '注册模块', 'title': '注册成功', 'url': 'http://api.nnzhp.cn/api/user/user_reg', 'method': 'POST', 'data': {'username': 'yingcr10', 'pwd': 'Ace123456', 'cpwd': 'Ace123456'}, 'check': {'error_code': 0, 'msg': '注册成功!'}}
注册模块 注册成功
{'model': '注册模块', 'title': '用户名长度小于6位,注册失败', 'url': 'http://api.nnzhp.cn/api/user/user_reg', 'method': 'POST', 'data': {'username': 'yingc', 'pwd': 'Ace123456', 'cpwd': 'Ace123456'}, 'check': {'error_code': 3002}}
注册模块 用户名长度小于6位,注册失败

三、通过ddt读取yaml测试数据

config.yaml数据文件与上文的一致。

# get_ddt.py

import requests
import unittest
import json
from ddt import ddt, data, unpack, file_data @ddt
class SignTest(unittest.TestCase): # 使用ddt加载yaml中的测试数据
@file_data("config.yaml")
def test_get_yaml(self,model,title,url,method,data,check):
# 提取分离各参数
model = model
title = title
url = url
method = method
data = data
check = check
self.sign_test(model,title,url,method,data,check) def sign_test(self,model,title,url,method,data,check):
print("模块: ", model)
print("用例标题: ", title)
response = requests.request(url=url, method=method, data=data).text
response = json.loads(response)
try:
# 通过断言,判断测试是否通过
assert check['error_code'] == response['error_code']
print("测试通过")
except Exception as e:
print("测试失败")
raise e if __name__ == "__main__":
unittest.main()
运行结果:

模块:  注册模块
用例标题: 注册成功
测试通过
模块: 注册模块
用例标题: 用户名长度小于6位,注册失败
测试通过
..
----------------------------------------------------------------------
Ran 2 tests in 0.188s OK

四、python中使用ddt+excel读取测试数据

大体思路:先从excel文件中读取数据,然后再用ddt加载已读取的数据。

# get_excel.py

from openpyxl import load_workbook

class ExcelData():

    def __init__(self, file="config.xlsx"):
'''
初始化Excel对象
'''
self.file = file
self.wb = load_workbook(self.file) def get_row_value(self, row, sheet_name="Sheet1"):
'''
获取Excel中某一行的数据
'''
sh = self.wb[sheet_name]
max_col = sh.max_column
row_value = []
for col in range(1, max_col+1):
value = sh.cell(row, col).value
row_value.append(value)
return row_value def get_all_row(self, sheet_name="Sheet1"):
'''
获取Excel中所有行的数据,并存放在列表中
'''
sh = self.wb[sheet_name]
max_row = sh.max_row
row_value = []
for row in range(2, max_row+1):
value = self.get_row_value(row)
row_value.append(value)
return row_value if __name__ == "__main__":
excel = ExcelData()
testdata = excel.get_all_row()
print(testdata)
# get_ddt.py

import requests
import unittest
from ddt import ddt, data, unpack, file_data
from get_excel import ExcelData @ddt
class SignTest(unittest.TestCase): # 从get_excel.py中读取测试数据
excel = ExcelData()
testdata = excel.get_all_row() @data(*testdata)
def test_sign(self, datas):
# 由于从excel中读取到的数据为列表形式,所以采用下标来提取各参数
ID = datas[0]
model = datas[1]
title = datas[2]
method = datas[3]
url = datas[4]
username = datas[5]
pwd = datas[6]
cpwd = datas[7]
check = datas[8]
body = {
"username": username,
"pwd": pwd,
"cpwd": cpwd
}
self.sign_test(ID,model,title,url,method,body,check) def sign_test(self,ID,model,title,url,method,body,check):
print("用例ID:", ID)
print("模块:", model)
print("用例标题:", title)
response = requests.request(url=url, method=method, data=body).text
try:
# 通过断言,比较实际结果是否与预期结果一致
# 由于从excel中读取到的check为str类型,所以response不用转换为dict,直接断言比较是否相等
assert check == response
print("测试通过")
except Exception as e:
print("测试失败")
raise e if __name__ == "__main__":
unittest.main()
运行结果:

用例ID: 001
模块: 注册模块
用例标题: 正确的用户名和密码,注册成功
.测试通过
用例ID: 002
模块: 注册模块
用例标题: 用户名长度小于6位,注册失败
.测试通过
OK
----------------------------------------------------------------------
Ran 2 tests in 0.190s Process finished with exit code 0
参考:https://www.jianshu.com/p/78998bcf3e05
参考:http://www.manongjc.com/detail/18-eosubecmlglohgb.html
 

python之ddt模块使用的更多相关文章

  1. python使用ddt模块对用例执行操作

    import time import unittest import ddt from selenium import webdriver TEST_URL = "http://www.ba ...

  2. python ddt模块

    ddt模块包含了一个类的装饰器ddt和两个方法的装饰器: data:包含多个你想要传给测试用例的参数: file_data:会从json或yaml中加载数据: 通常data中包含的每一个值都会作为一个 ...

  3. 【python+ddt】DDT模块的使用

    ddt模块包含了一个类的装饰器ddt和两个方法的装饰器: data:包含多个你想要传给测试用例的参数: file_data:会从json或yaml中加载数据: unpanck:通常data中包含的每一 ...

  4. DDT模块

    转自: https://www.cnblogs.com/frost-hit/p/8277637.html Python DDT(data driven tests)模块心得   关于ddt模块的一些心 ...

  5. Python 安装第三方模块时 报Retrying(Retry(total=4, connect=None, read=None, redirect=None, status=None))...[WinError 10061]由于目标计算机积极拒绝,无法连接 错误

    今日在安装ddt模块时(Windows系统),cmd报了一个以前从未见过的错误,如下图所示: 经百度,知是镜像源的问题,将安装命令改成如下命令: pip install ddt -i https:// ...

  6. python之platform模块

    python之platform模块 ^_^第三个模块从天而降喽!! 函数列表 platform.system() 获取操作系统类型,windows.linux等 platform.platform() ...

  7. python之OS模块详解

    python之OS模块详解 ^_^,步入第二个模块世界----->OS 常见函数列表 os.sep:取代操作系统特定的路径分隔符 os.name:指示你正在使用的工作平台.比如对于Windows ...

  8. python之sys模块详解

    python之sys模块详解 sys模块功能多,我们这里介绍一些比较实用的功能,相信你会喜欢的,和我一起走进python的模块吧! sys模块的常见函数列表 sys.argv: 实现从程序外部向程序传 ...

  9. 学习PYTHON之路, DAY 6 - PYTHON 基础 6 (模块)

    一 安装,导入模块 安装: pip3 install 模块名称 导入: import module from module.xx.xx import xx from module.xx.xx impo ...

随机推荐

  1. Deep learning-based personality recognition from text posts of online social networks 阅读笔记

    文章目录 一.摘要 二.模型过程 1.文本预处理 1.1 文本切分 1.2 文本统一 2. 基于统计的特征提取 2.1 提取特殊的语言统计特征 2.2 提取基于字典的语言特征 3. 基于深度学习的文本 ...

  2. python 文件读写with open模式r,r+,w,w+,a,a+的区别

    模式 可做操作 若文件不存在 是否覆盖 r 只能读 报错 - r+ 可读可写 报错 是 w 只能写 创建 是 w+ 可读可写 创建 是 a 只能写 创建 否,追加写 a+ 可读可写 创建 否,追加写

  3. Testflight无法接入App Store connect,对TF上架的应用会造成什么影响吗?

    感觉进入8月份以来,苹果也进入了多事之秋.不仅是App Store被下架,testflight也频频出问题,很多人反馈出现了Testflight无法接入App Store connect的问题,我们之 ...

  4. 第6章 运行Spark SQL CLI

    第6章 运行Spark SQL CLI Spark SQL CLI可以很方便的在本地运行Hive元数据服务以及从命令行执行查询任务.需要注意的是,Spark SQL CLI不能与Thrift JDBC ...

  5. oracle修改用户密码操作

    打开命令提示框输入以下内容: 1.输入:sqlplus /nolog //进入oralce控制台2.输入:conn /as sysdba //以管理员权限登录3.输入:alter user apps ...

  6. 团队作业1——团队展示&选题 (追忆少年)

    目录 一,团队展示 1.1队名 1.2队员学号 1.3项目描述 1.4队员风采 1.5团队分工 1.6团队合照 1.7团队特色 (一)目标导向 (二)协作基础 (三)共同的规范和方法 (四)技术或技能 ...

  7. 查询Linux CPU架构

    一.背景 Ubuntu上需要安装测试个软件wkhtmltopdf,但是下载时,需要知道系统架构,故做记录 二.查看linux架构 dpkg 命令 dpkg 的命令可用于查看 Debian/ Ubunt ...

  8. C# DataTable查询示例

    代码 public void Test() { #region 初始化数据 /* 数据 张三 语文 34.00 张三 数学 58.00 张三 英语 61.00 李四 语文 45.00 李四 数学 87 ...

  9. 记录laravelchina中的微信小程序教程的npm install安装报错

    npm安装报错时 npm ERR! code EIOnpm ERR! syscall symlinknpm ERR! path ../@babel/parser/bin/babel-parser.js ...

  10. 多层v-for循环嵌套导致v-model双向绑定失败,页面不重新渲染

    数据格式是数组包对象,对象里面再包数组,数组再包对象,如下: 外层for遍历出editInfo里面所有的属性,内层for遍历Options. 最终实现样子 两个问题: 1.点加减按钮的时候往optio ...