Python Unittest ddt数据驱动的实现

作者:梦琪丁岚 时间:2023-10-29 14:54:14 

1、数据驱动介绍:

  • @ddt.ddt(类装饰器,申明当前类使用ddt框架)

  • @ddt.data(函数装饰器,用于给测试用例传递数据),支持传python所有数据类型:数字(int,long,float,compix),字符串,列表1ist,元组tuple,集合,编写阅读数据文件的函数、@data入口参数加*读取

  • @ddt.unpack(函致装饰器,将传输的数据包解包),一般作用于元组tuple和列表list、字典(参数名字和个数需要与字典的键保持一致)(数组、字符串不需要)

  • @ddt.file_data(函数装饰器,可直接读取yaml/json文件)

2、数据驱动和关键驱动的区别:

Data-Driven Tests(DDT)即数据驱动测试,可以实现不同数据运行同一个测试用例。ddt本质其实就是装饰器,一组数据一个场景。
关键字驱动(核心:把业务逻相封装成关键字login,只需要调用login。)

3、混合驱动模式(关键字驱动+数据驱动)

4、在进行数据驱动测试实战:需要在测试类上使用@ddt.ddt装饰器,在测试用例上使用@ddt.data装饰器。

(1)单一参数:导包——写一个参数(列表、数字、字符串)-----设置@ddt.data装饰器写入参数名----方法中写入形参*data----调用参数内容

(2)多参数的数据驱动测试(一个测试参数中含多个元素):导包——设置@ddt装饰器——设置@unpack解包——写入参数——形参传递——调用

(3)txt文件传参

(4)json文件传参

(5)yaml文件传参

(6)xlsx文件传参

注意:Python中传递可变参数:*代表顺序阅读列表类型,**代表顺序阅读对象(字典)类型,点击阅读可变参数部分可了解相关机制

# 1、单一参数的数据驱动

# 前置步骤:
# 使用语句import unittest导入测试框架
# 使用语句from ddt import ddt, data导入单一参数的数据驱动需要的包

# 示例会执行三次test,参数分别为'666','777','888'
import ddt
import unittest
@ddt.ddt  # 设置@ddt装饰器
class BasicTestCase(unittest.TestCase):
   @ddt.data('666', '777', '888')  # 设置@data装饰器,并将传入参数写进括号
   def test(self, *data):  # test入口设置形参
       print('数据驱动的number:', data)
# 程序会执行三次测试,入口参数分别为666、777、888

# 2、多参数的数据驱动
# 在单一参数包的基础上,额外导入一个unpack的包,from ddt import ddt, data, unpack
# 步骤:导包——设置@ddt装饰器——设置@unpack解包——写入参数——形参传递——调用
import ddt
import unittest

Testdata = [
   {"username": "admin", "password": "123456", "excepted": {'code': '200', 'msg': '登录成功'}},
   {"username": None, "password": "1234567", "excepted": {'code': '400', 'msg': '用户名或密码不能为空'}},
   {"username": "admin", "password": None, "excepted": {'code': '400', 'msg': '用户名或密码不能为空'}},
   {"username": "admin", "password": "123456789", "excepted": {'code': '404', 'msg': '用户名或密码错误'}},
]

@ddt.ddt
class BasicTestCase(unittest.TestCase):

#方式一:直接将列表放到data
   @ddt.data(['张三', '18'], ['李四', '19'])  # 设置@data装饰器,并将同一组参数写进中括号[]
   @ddt.unpack  # 设置@unpack装饰器顺序解包,缺少解包则相当于name = ['张三', '18']
   def test(self, name, age):
       print('姓名:', name, '年龄:', age)
# 程序会执行两次测试,入口参数分别为['张三', '18'],['李四', '19']

#方式二:写一个列表后,使用*访问列表到data
   @ddt.data(*Testdata)
   @ddt.unpack # 设置@unpack装饰器顺序解包
   def test_DataDriver(self, *Data):
       #print('DDT数据驱动实战演示:', Data)
       res = login.login_check(Testdata['username'], Testdata['password'])
       self.assertEqual(res, Testdata['excepted'])

#3、 txt文件接收参数
# 新建num文件,txt格式
   # (1)单一参数按行存储777,888,999
   # (2)多参数txt文件
       # dict文件内容(参数列表)(按行存储):
       # 张三,18
       # 李四,19
# 编辑阅读数据文件的函数
# 记住读取文件一定要设置编码方式,否则读取的汉字可能出现乱码!!!!!!
import ddt
import unittest
def read_num():
   lis = []    # 以列表形式存储数据,以便传入@data区域
   with open('num.txt', 'r', encoding='utf-8') as file:    # 以只读'r',编码方式为'utf-8'的方式,打开文件'num',并命名为file
       for line in file.readlines():   # 循环按行读取文件的每一行
           lis.append(line.strip('\n'))  #单一参数,每读完一行将此行数据加入列表元素,记得元素要删除'/n'换行符!!!
           #lis.append(line.strip('\n').split(','))  # 多参驱动,删除换行符,根据,分割后,列表为['张三,18', '李四,19', '王五,20']
       return lis    # 将列表返回,作为@data接收的内容
@ddt.ddt
class BasicTestCase(unittest.TestCase):
   @ddt.data(*read_num())  # 入口参数设定为read_num(),因为返回值是列表,所以加*表示逐个读取列表元素
   #txt表格有多少个值,设置多少个接收参数的形参
   def test(self, name,age):
       print('数据驱动的number:', name,age)

# 4、JSON文件传参:数据分离
# 多参数——json文件
# 步骤和单一参数类似,仅需加入@unpack装饰器以及多参数传参入口
# dict文件内容(参数列表)(非规范json文件格式):
# 单一参数:["666","777","888"]
# 多个参数:[["张三", "18"], ["李四", "19"], ["王五", "20"]]
# 注意json文件格式字符串用双引号
import ddt
import unittest
import json
def read_dict_json():
   return json.load(open('dict.json', 'r', encoding='utf-8'))  # 使用json包读取json文件,并作为返回值返回
@ddt.ddt
class BasicTestCase(unittest.TestCase):
   @ddt.data(*read_dict_json())
   @ddt.unpack     # 使用@unpack装饰器解包
   def test(self, name, age):    # 因为是非规范json格式,所以形参名无限制,下文会解释规范json格式
       print('姓名:', name, '年龄:', age)

# 4、JSON文件传参:数据分离
# json文件三种形式:
# (1)单一参数:["666","777","888"]
# (2)多个参数:[["张三", "18"], ["李四", "19"], ["王五", "20"]]
# (3)JSON格式读取,每一组参数以对象形式存储:
# [
#   {"name":"张三", "age":"18"},
#   {"name":"李四", "age":"19"},
#   {"name":"王五", "age":"20"}
# ]
# 单一参数时无需使用unpack,多参数需要使用unpack解包,注意json文件格式字符串用双引号
import ddt
import unittest
import json

#方式1:非正式json格式使用
def read_dict_json():
   return json.load(open('dict.json', 'r', encoding='utf-8'))  # 使用json包读取json文件,并作为返回值返回

#方式2:JSON格式读取,提取已读完后的json文件(字典形式),通过遍历获取元素,并返回
def read_dict_json():
   lis = []
   dic = json.load(open('dict.json', 'r', encoding='utf-8'))
   # 此处加上遍历获取语句,下文yaml格式有实例,方法一样
   for item in dic:
       lis.append(item)
   return lis

@ddt.ddt
class BasicTestCase(unittest.TestCase):
   @ddt.data(*read_dict_json())
   @ddt.unpack     # 使用@unpack装饰器解包
   def test(self, name, age):    # 因为是非规范json格式,所以形参名无限制,下文会解释规范json格式
       print('姓名:', name, '年龄:', age)

#5、多参数yaml
# 以对象形式存储yml数据(字典)
# yaml格式文件内容
# -
#   name: 张三
#   age: 18
# -
#   name: 李四
#   age: 19
# -
#   name: 王五
#   age: 20
# '-'号之后一定要打空格!!!
# ':'号之后一定要打空格!!!

# 入口参数与数据参数key命名统一即可导入
import ddt
import unittest
import yaml
@ddt.ddt
class BasicTestCase(unittest.TestCase):

#方式1:形参入口和数据参数key命名统一
   @ddt.file_data('./data/dict.yml')
   def test(self, name, age):  # 设置入口参数名字与数据参数命名相同即可
       print('姓名是:', name, '年龄为:', age)

#方式2:入口参数与数据参数命名不统一
   @ddt.file_data('./data/dict.yml')
   def test(self, **cdata):  # Python中可变参数传递的知识:**按对象顺序执行
       print('姓名是:', cdata['name'], '年龄为:', cdata['age'])    # 通过对象访问语法即可调用

例子如下:

方式一:测试数据直接写成列表形式,使用ddt.data(*Data)传值

##2.12.2  DDT在自动化测试中的应用(传列表)

import ddt
import unittest

# 给4条测试数据
   Testdata = [
       {"username": "admin", "password": "123456", "excepted": {'code': '200', 'msg': '登录成功'}},
       {"username": None, "password": "1234567", "excepted": {'code': '400', 'msg': '用户名或密码不能为空'}},
       {"username": "admin", "password": None, "excepted": {'code': '400', 'msg': '用户名或密码不能为空'}},
       {"username": "admin", "password": "123456789", "excepted": {'code': '404', 'msg': '用户名或密码错误'}},
   ]
@ddt.ddt
class TestModules(unittest.TestCase):
   def setUp(self):
       print('testcase beaning....')
   def tearDown(self):
       print('testcase ending.....')

@ddt.data(*Data)
   def test_DataDriver(self,Data):
       #print('DDT数据驱动实战演示:',Testdata)
       res = login.login_check(Testdata['username'], Testdata['password'])
       self.assertEqual(res, Testdata['excepted'])
if __name__ == '__main__':
   unittest.main()

方式二:数据写到方法形式readData(),使用ddt.data(*readData())传值

import ddt
import unittest

# 给4条测试数据
def readData():
   Testdata = [
       {"username": "admin", "password": "123456", "excepted": {'code': '200', 'msg': '登录成功'}},
       {"username": None, "password": "1234567", "excepted": {'code': '400', 'msg': '用户名或密码不能为空'}},
       {"username": "admin", "password": None, "excepted": {'code': '400', 'msg': '用户名或密码不能为空'}},
       {"username": "admin", "password": "123456789", "excepted": {'code': '404', 'msg': '用户名或密码错误'}},
   ]
   return TestData

@ddt.ddt
class TestModules(unittest.TestCase):
   def setUp(self):
       print('testcase beaning....')
   def tearDown(self):
       print('testcase ending.....')
   @ddt.data(*readData())
   def test_DataDriver(self,Data):
       #print('DDT数据驱动实战演示:',Testdata)
       res = login.login_check(Testdata['username'], Testdata['password'])
       self.assertEqual(res, Testdata['excepted'])
if __name__ == '__main__':
   unittest.main()

来源:https://blog.csdn.net/mengluzhixing/article/details/129212023

标签:Python,Unittest,ddt
0
投稿

猜你喜欢

  • HTTP服务压力测试工具及相关术语讲解

    2024-05-08 10:23:31
  • SQL Server中row_number分页查询的用法详解

    2024-01-21 20:15:01
  • widows下安装pycurl并利用pycurl请求https地址的方法

    2023-07-09 03:21:18
  • Python使用scipy模块实现一维卷积运算示例

    2022-10-18 07:15:19
  • Golang Gob编码(gob包的使用详解)

    2024-02-22 02:16:46
  • python函数装饰器用法实例详解

    2023-09-23 09:40:16
  • 对Python 简单串口收发GUI界面的实例详解

    2023-03-29 05:50:18
  • yolov5特征图可视化的使用步骤

    2022-07-22 01:25:40
  • 不用加载Include文件也能生成选择列表吗?

    2009-10-29 12:30:00
  • tensorflow使用指定gpu的方法

    2022-10-23 16:00:31
  • JavaScript实现鼠标经过显示下拉框

    2024-04-28 09:52:36
  • 使用C#配合ArcGIS Engine进行地理信息系统开发

    2023-06-25 16:35:01
  • Python函数装饰器的使用详解

    2023-04-30 14:47:24
  • oracle用户权限管理使用详解

    2024-01-17 13:06:58
  • Go语言Mock使用基本指南详解

    2024-05-08 10:15:03
  • Python识别html主要文本框过程解析

    2023-11-09 01:31:52
  • python十进制转二进制的详解

    2023-06-07 23:39:33
  • Oracle如何批量将表中字段名全转换为大写(利用简单存储过程)

    2024-01-22 11:23:41
  • echarts报错Cannot read properties of null (reading ‘getAttribute‘)的解决

    2024-04-17 10:04:06
  • Python使用matplotlib.pyplot as plt绘图图层优先级问题

    2022-06-10 18:00:37
  • asp之家 网络编程 m.aspxhome.com