Unittest自动化测试框架教程(四)——Python中的数据驱动测试DDT

 “ 数据驱动测试DDT(Data Drivern test),是自动化测试领域优势中亮眼的闪光点,在unittest测试框架中对数据驱动更是提供了强大的支持,文章通过基础概念的引入,介绍了数据驱动的概念,并且通过实例介绍了Python中使用数据驱动txt文件、json文件、yaml文件的测试方法。”

PS:“ 测试老手可根据需要自由获取所需内容,其余的建议从头阅读。”

  • 博主每篇文章的注释都是干货!每个代码段都有详细注释,一定要认真看注释!!!
  • 重要的事情说三遍:一定要看注释!!!一定要看注释!!!一定要看注释!!!

 前情提要

  • 此前博主的系列专栏Unittest自动化测试框架教程详细介绍了测试用例的基本框架、测试夹具的使用以及测试用例的跳过教学,在熟悉测试用例基本框架的基础上,本文开始讲解何为数据驱动测试,以前几种常见格式的数据驱动测试方法

 数据驱动测试的基本概念、引读

  引读、基本概念

  • 当我们进行测试时遇到执行步骤相同,只需要改变入口参数的测试时,使用DDT可以简化代码
  • 一定要认真看注释!!!
# 示例:
# 首先,我们观察这三个测试用例,我们会发现,三个测试用例除了入口参数需要变化,
# 其测试执行语句都是相同的,因此,为了简化测试代码,我们可以使用数据驱动测试的理论将三个方法写作一个方法

# 未使用数据驱动测试的代码:
class BasicTestCase(unittest.TestCase):
    def test1(self, num1):
        num = num1 + 1
        print('number:', num)

    def test2(self, num2):
        num = num2 + 1
        print('number:', num)

    def test3(self, num3):
        num = num3 + 1
        print('number:', num)

# 使用数据驱动测试的代码,执行效果与上文代码相同此处只需要了解大概框架,详细步骤下文会解释
@ddt
class BasicTestCase(unittest.TestCase):
    @data('666', '777', '888')    
    def test(self, num):     
        print('数据驱动的number:', num)
  • 相信到这里读者对数据驱动已经有了一定了解
  • 接下来我们开始进入DDT的学习

  单一参数的数据驱动测试

  • 步骤:导包——设置@ddt装饰器——写入参数——形参传递——调用
  • 一定要认真看注释!!!
# 单一参数的数据驱动

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

# 示例会执行三次test,参数分别为'666','777','888'

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

  多参数的数据驱动测试(一个测试参数中含多个元素)

  • 步骤:导包——设置@ddt装饰器——设置@unpack解包——写入参数——形参传递——调用
  • 一定要认真看注释!!!
# 多参数的数据驱动
# 在单一参数包的基础上,额外导入一个unpack的包,from ddt import ddt, data, unpack
# 步骤:导包——设置@ddt装饰器——设置@unpack解包——写入参数——形参传递——调用

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

 


  • 看到这里,笔者以及介绍完了数据驱动测试的基本概念,以及单参数、多参数数据驱动的区别,但是,我们是将数据和代码写在一起,接下来笔者会介绍数据驱动测试的核心理念——数据与代码分离!!!(数据和代码在不同的文件里,方便维护代码和快速修改数据)
  • 数据驱动测试的核心——数据与代码分离
  • 接下来介绍txt格式、json格式、yaml格式数据的单参数、多参数数据驱动方法

txt格式文件驱动

单一参数数据驱动

  • 核心:编写阅读数据文件的函数、@data入口参数加*读取
  • 一定要认真看注释!!!
# 单一参数txt文件
# 新建num文件,txt格式,按行存储777,888,999
# num文件内容(参数列表):
# 777
# 888
# 999
# 编辑阅读数据文件的函数
# 记住读取文件一定要设置编码方式,否则读取的汉字可能出现乱码!!!!!!
def read_num():
    lis = []    # 以列表形式存储数据,以便传入@data区域
    with open('num', 'r', encoding='utf-8') as file:    # 以只读'r',编码方式为'utf-8'的方式,打开文件'num',并命名为file
        for line in file.readlines():   # 循环按行读取文件的每一行
            lis.append(line.strip('\n'))  # 每读完一行将此行数据加入列表元素,记得元素要删除'/n'换行符!!!
        return lis    # 将列表返回,作为@data接收的内容
@ddt
class BasicTestCase(unittest.TestCase):
    @data(*read_num())  # 入口参数设定为read_num(),因为返回值是列表,所以加*表示逐个读取列表元素
    def test(self, num):
        print('数据驱动的number:', num)
# 测试结果见下图

 

多参数数据驱动 

  • 核心:读取函数中的数据分割、@unpack解包
  • 一定要认真看注释!!!
# 多参数txt文件
# dict文件内容(参数列表)(按行存储):
# 张三,18
# 李四,19
# 王五,20
def read_dict():
    lis = []  # 以列表形式存储数据,以便传入@data区域
    with open('dict', 'r', encoding='utf-8') as file:  # 以只读'r',编码方式为'utf-8'的方式,打开文件'num',并命名为file
        for line in file.readlines():  # 循环按行读取文件的每一行
            lis.append(line.strip('\n').split(','))  # 删除换行符后,列表为['张三,18', '李四,19', '王五,20']
            # 根据,分割后,列表为[['张三', '18'], ['李四', '19'], ['王五', '20']]
        return lis  # 将列表返回,作为@data接收的内容


@ddt
class BasicTestCase(unittest.TestCase):
    @data(*read_dict())  # 加*表示逐个读取列表元素,Python中可变参数,*表示逐个读取列表元素,列表为[['张三', '18'], ['李四', '19'], ['王五', '20']]
    @unpack  # 通过unpack解包,逐个传参,缺少这句会将['张三', '18']传给name,从而导致age为空
    def test(self, name, age):  # 设置两个接收参数的形参
        print('姓名为:', name, '年龄为:', age)
# 测试结果见下图

 


json格式文件驱动

单一参数数据驱动

  • 核心:使用json解析包读取文件
  • 一定要认真看注释!!!
# 单一参数——json文件
# num.json文件内容(参数列表)(注意命名后缀):
# ["666","777","888"]
# 注意JSON文件中,数据元素如果是字符串必须得用双引号
# 使用语句import json导入json包,快速读取文件用
def read_num_json():
    return json.load(open('num.json', 'r', encoding='utf-8'))  # 使用json包读取json文件,并作为返回值返回,注意读取的文件名
@ddt  # 数据驱动步骤和txt相同
class BasicTestCase(unittest.TestCase):
    @data(*read_num_json())
    def test(self, num):
        print('读取的数字是', num)

多参数数据驱动(以列表形式存储多参数)

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

 

 多参数数据驱动(以对象形式存储多参数)

  • 核心:形参名字与json中对象key名相同
  • 一定要认真看注释!!!
# 规范json格式读取,每一组参数以对象形式存储
# dict文件内容:
# [
#   {"name":"张三", "age":"18"},
#   {"name":"李四", "age":"19"},
#   {"name":"王五", "age":"20"}
# ]

def read_dict_json():
    return json.load(open('dictx.json', 'r', encoding='utf-8'))  # 使用json包读取json文件,并作为返回值返回
@ddt
class BasicTestCase(unittest.TestCase):
    @data(*read_dict_json())
    @unpack
    def test(self, name, age):    # 令形参名字和json中命名相同name=name,age=age
        print('姓名:', name, '年龄:', age)
# 测试结果见下图

# 非常特殊情况:
# 形参名字和json中对象命名无法相同,则更改读取函数
# 提取已读完后的json文件(字典形式),通过遍历获取元素,并返回
# def read_dict_json():
#     li = []
#     dic = json.load(open('dict.json', 'r', encoding='utf-8'))
#     # 此处加上遍历获取语句,下文yaml格式有实例,方法一样
#     return li

  


 yaml格式文件驱动

  • 在自动化测试领域中,yaml数据格式是举足轻重的,因此笔者在此特地进行yaml格式解析

  • 在unittest测试框架中,对yaml数据格式的支持十分强大,使用非常方便

  • yaml文件的数据驱动执行代码十分简单!!!(但是要注意细节)

  • 学习更多yaml数据格式的知识,请点击链接yaml实例教程icon-default.png?t=M3K6http://t.csdn.cn/RBcwq

单一参数数据驱动

  • 核心:使用yaml解析包读取文件,导入file_fata驱动数据
  • 一定要认真看注释!!!
# YAML数据格式驱动
# 单一参数
# import yaml   # 导入yaml解析包
# from ddt import file_data     # 导入file_data驱动数据
# yaml格式文件内容
# - 666
# - 777
# - 888
# '-'号之后一定要打空格!!!
@ddt
class BasicTestCase(unittest.TestCase):
    @file_data('num.yml')   # 采用文件数据驱动
    def test(self, num):
        print('读取的数字是', num)
# 测试结果见下图

   

 多参数数据驱动

  • 核心:形参入口和数据参数key命名统一(下文介绍参数无法统一的解决办法)
  • 一定要认真看注释!!!
# 多参数yaml
# 以对象形式存储yml数据(字典)
# yaml格式文件内容
# -
#   name: 张三
#   age: 18
# -
#   name: 李四
#   age: 19
# -
#   name: 王五
#   age: 20
# '-'号之后一定要打空格!!!
# ':'号之后一定要打空格!!!

# 入口参数与数据参数key命名统一即可导入
@ddt
class BasicTestCase(unittest.TestCase):
    @file_data('dict.yml')
    def test(self, name, age):  # 设置入口参数名字与数据参数命名相同即可
        print('姓名是:', name, '年龄为:', age)
# 测试结果见下图

  • 特殊情况:当入口与文件中数据参数无法统一命名时,解决办法 
# 入口参数与数据参数命名不统一
@ddt
class BasicTestCase(unittest.TestCase):
    @file_data('dict.yml')
    def test(self, **cdata):  # Python中可变参数传递的知识:**按对象顺序执行
        print('姓名是:', cdata['name'], '年龄为:', cdata['age'])    # 通过对象访问语法即可调用
  • Python中传递可变参数:*代表顺序阅读列表类型,**代表顺序阅读对象(字典)类型,点击阅读可变参数部分可了解相关机制


 核心总结

  • 数据驱动——代码与数据分离
  • yaml数据格式的数据驱动——最为简单快捷

💗 “纵苍茫大地山河璀璨,野花芳草星河烂漫,终不及你嫣然一笑的匆然来犯。” 

                                                                                                    ——Created By 是羽十八ya

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是羽十八ya

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值