从零开始编写Web自动化测试脚本(九)--ddt数据驱动

第一章 Selenium+WebDriver环境搭建
第二章 Selenium定位方式
第三章 元素常用属性
第四章 自动化中的三种等待
第五章 自动化浏览器设置及句柄、窗口切换操作
第六章 鼠标、键盘操作
第七章 javascript在自动化中的应用
第八章 unittest&断言
第九章 ddt数据驱动
第十章 测试框架搭建过程Python+Selenium+BeautifulReport



一、数据驱动的概述

1、数据驱动的简介

数据驱动:数据驱动测试的方法是将测试数据与测试用例脚本分离的一种方法。所谓数据驱动就是
同一段代码,参数一样,但是函数内部做了处理,所以输入不同的数据(值),得到不同的结果。
比如果输入一个名字,你输入张三得到的结果是帅哥,你输入小雨得到的结果是美女,那这个就是
数据驱动。

2、数据驱动的意义

①只需要创建一个测试脚本就可以处理各种不同的测试数据和条件的组合;
②使用数据驱动的模式,根据业务逻辑分解测试数据,并且定义变量,使用外部的excel里的数据
使其参数化, 从而避免使用源测试脚本中的固定数据,这种方式可以将测试脚本与测试数据分
开,使得测试脚本在不同的 数据集合下高度复用。
③数据驱动的模式不仅可以帮助增加类似复杂条件场景下的测试覆盖,还可以极大的减少对测试
代码的编写和维护工作。

3、常见数据驱动的方式

①ddt:yaml,excel、xmind,mysql(表中的一条就代表一个用例)
②pytest:参数化
工作场景:
①去读取文件获取所有的数据
②再用ddt * ,unpack,解析成具体的用例

二、ddt概述

1、ddt简介

ddt:Data Driven Testing,数据驱动,简单来说就是测试数据的参数化;
ddt是第三方库,可以通过pip install ddt来下载

pip install ddt

2、ddt包含类的装饰器ddt、方法装饰器data

①ddt.ddt:装饰类,用于unittest.TestCase子类的类装饰器。
②ddt.data(value):添加到unittest.TestCase测试用例上的方法装饰器。作用:专门给测试用例导入数据
的,value是直接操作的数据。
• @data(a,b) 那么a和b各自作为参数使用,各运行一次用例,共执行2次用例
• @data([a,d],[c,d]) 那么[a,b]当成一个参数传入用例运行,共执行2次用例
③ddt.unpack:传递的是复杂的数据结构时使用,主要用于拆分数据。比如使用元组或者列表,添加
unpack之后,ddt会自动把元组或者列表中的值拆分成多个值,依次传给多个参数接收。

3、ddt使用

第一步:导包

import ddt 或者 from ddt import ddt

第二步:调用装饰类
• 写在测试类前面

@ddt.ddt 或者 @ddt

第三步:调用方法装饰器
• 写在测试方法前面

@ddt.data(value1,value2...) 或者 @data(value1,value2...)

data()里的数据可以是单个数字,字符,也可以为元组,列表,字典。

4、实例操作

举个例子:比如我们在百度页面,搜索三个字符串,普通写法如下:

from selenium import webdriver
from selenium.webdriver.common.by import By
import time
import unittest

class Testcase(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(3)
        self.driver.maximize_window()
        self.driver.get("https://www.baidu.com")

    def tearDown(self):
        time.sleep(3)
        self.driver.quit()

    def test_001(self):
        self.driver.find_element(By.ID, "kw").send_keys("001")
        self.driver.find_element(By.ID, "su").click()

    def test_002(self):
        self.driver.find_element(By.ID, "kw").send_keys("002")
        self.driver.find_element(By.ID, "su").click()

    def test_003(self):
        self.driver.find_element(By.ID, "kw").send_keys("003")
        self.driver.find_element(By.ID, "su").click()

if __name__ == '__main__':
    unittest.main

再使用ddt后,写法如下:

from selenium import webdriver
from selenium.webdriver.common.by import By
import time
import unittest
import ddt

#调用装饰类ddt
@ddt.ddt
class Testcase(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(3)
        self.driver.maximize_window()
        self.driver.get("https://www.baidu.com")

    def tearDown(self):
        time.sleep(3)
        self.driver.quit()
        
	#调用ddt方法装饰器。使用ddt装饰器只需将测试数据传入即可,相当于执行三条用例
    @ddt.data("001", "002", "003")
    def test_001(self, value):
        self.driver.find_element(By.ID, "kw").send_keys(value)
        self.driver.find_element(By.ID, "su").click()

if __name__ == '__main__':
    unittest.main

当然,我们也可以传入列表,元组,字典等。需要注意的是,这时我们得先使用@unpack进行解包操作,例如:

from selenium import webdriver
from selenium.webdriver.common.by import By
import time
import unittest
import ddt

@ddt.ddt
class Testcase(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(3)
        self.driver.maximize_window()
        self.driver.get("https://www.baidu.com")

    def tearDown(self):
        time.sleep(3)
        self.driver.quit()

    #传入列表数据
    @ddt.data(["001-1,","001-2"],["002-1,","002-2"],["003-1,","003-2"])
    #解包,分解成两个参数,分别传递给value1和value2
    @ddt.unpack
    def test_001(self, value1,value2):
        self.driver.find_element(By.ID, "kw").send_keys(value1)
        self.driver.find_element(By.ID, "kw").send_keys(value2)

if __name__ == '__main__':
    unittest.main

当列表嵌套元祖时,我们使用*先将1个整体解包成多个元素,unpack再将元素解包成多个参数值,分别传递进去,例如:

from selenium import webdriver
from selenium.webdriver.common.by import By
import time
import unittest
import ddt

@ddt.ddt
class Testcase(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(3)
        self.driver.maximize_window()
        self.driver.get("https://www.baidu.com")

    def tearDown(self):
        time.sleep(3)
        self.driver.quit()

    # 传入列表嵌套元祖数据,注意*号
    @ddt.data(*[("001-1,", "001-2")], *[("002-1,", "002-2")], *[("003-1,", "003-2")])
    # 解包,分解成两个参数,分别传递给value1和value2
    @ddt.unpack
    def test_001(self, value1, value2):
        self.driver.find_element(By.ID, "kw").send_keys(value1)
        self.driver.find_element(By.ID, "kw").send_keys(value2)
        time.sleep(3)

if __name__ == '__main__':
    unittest.main

5、总结

@data 装饰符可以把参数当做测试数据,参数可以是单个值/多个值:字符串,列表,元组,字典
@data(“001”) #单个值,代表一个数据,会执行一个用例
@data(“001-1”, “001-2”) #多个值,代表的多个数据,会执行多个(2个)用例
@data((“001-1”, “001-2”), (“002-1”, “002-2”)) #多个值,值为元组(列表,字典),每一个整体代表一个用
例 ,有多个整体,则会执行多个用例。对于列表和元组,需要使用 @unpack 装饰符把元组和列表解析
成多个参数,
@data({‘name’:‘001-1’,‘pwd’:‘001-2’},{‘name’:‘002-1’,‘pwd’:‘002-2’}) #对于字典,除了需要使用@unpack 解析层多个参数外,而且函数中的形参还必须与@data字典中的key一致,否则会报错
@data(*[(‘001-1’,‘001-2’),(‘002-1’,‘002-2’)]) #所有的用例元素组装成一个大列表,*解包多个用例,@unpack再把一个整体的值(用例)解包成具体的参数,用例方法需要用相对应的参数个数来接收。

三、yaml文件数据驱动

测试用例的数据存储在yaml文件中,通过ddt读取yaml文件中的数据来实现多用例执行。
ddt.file_data(file):添加到unittest.TestCase测试用例上的方法装饰器。
作用:专门给测试用例导入数据的,数据是从外部文件中获取来的。
• file是文件目录的路径。
• 新建yaml文件,(-表示测试用例起始位置,缩进代表字典形式,'-'缩进代表list)

实例一:yaml数组
以 - 开头的行表示构成一个数组:

在这里插入图片描述

from selenium import webdriver
from selenium.webdriver.common.by import By
import time
import unittest
import ddt

# 调用装饰类ddt
@ddt.ddt
class Testcase(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(3)
        self.driver.maximize_window()
        self.driver.get("https://www.baidu.com")

    def tearDown(self):
        time.sleep(3)
        self.driver.quit()

    #用file_data方法加载yaml文件,会用yaml中的关键字,执行三条用例
    @ddt.file_data("111.yaml")
    def test_001(self, searchword):
        self.driver.find_element(By.ID, "kw").send_keys(searchword)
        time.sleep(3)

if __name__ == '__main__':
    unittest.main
实例二:yaml对象
对象键值对使用冒号结构表示 key: value,冒号后面要加一个空格。

在这里插入图片描述

from selenium import webdriver
from selenium.webdriver.common.by import By
import time
import unittest
import ddt

# 调用装饰类ddt
@ddt.ddt
class Testcase(unittest.TestCase):

    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(3)
        self.driver.maximize_window()
        self.driver.get("https://www.baidu.com")

    def tearDown(self):
        time.sleep(3)
        self.driver.quit()

    # 用file_data方法加载yaml文件
    @ddt.file_data("111.yaml")
    def test_001(self, **kwargs):
        searchword = kwargs.get("searchword")
        self.driver.find_element(By.ID, "kw").send_keys(searchword)
        time.sleep(3)

if __name__ == '__main__':
    unittest.main

四、excel文件数据驱动

1、读取excel数据-xlrd,openpyxl都可以,以行的方式读取所有的数据。
存储的格式为:[[‘user1’, 111111], [‘user2’, 222222], [‘user3’, 333333]]
在这里插入图片描述

import xlrd

# 读取excel数据方法
def readExceldDate(filename):
    book = xlrd.open_workbook(filename)
    sheet1 = book.sheet_by_index(0)
    rows = sheet1.nrows
    datalist = []
    for i in range(1, rows):
        datalist.append(sheet1.row_values(i))
    return datalist

print(readExceldDate("test.xlsx"))

注意:如果使用python的xlrd读取Excel文件时报错,将xlrd卸载后,安装1.2.0版本

pip3 install xlrd==1.2.0

2、用@data读取获取的数据:@data([[‘user1’, 111111], [‘user2’, 222222], [‘user3’, 333333]] )

import unittest
import ddt
import xlrd

# 读取excel数据方法
def readExceldDate(filename):
    book = xlrd.open_workbook(filename)
    sheet1 = book.sheet_by_index(0)
    rows = sheet1.nrows
    datalist = []
    for i in range(1, rows):
        datalist.append(sheet1.row_values(i))
    return datalist

# print(readExceldDate("test.xlsx"))

@ddt.ddt()
class TestCase(unittest.TestCase):
    @ddt.data(*readExceldDate("test.xlsx"))
    @ddt.unpack
    def test001(self, user, pwd):
        print(user, pwd)

if __name__ == '__main__':
    unittest.main

随手点赞一次,运气增加一份。

  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

拒绝内卷的小测试

感谢老板的投喂

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

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

打赏作者

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

抵扣说明:

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

余额充值