前言

网盗概念^-^相同的测试脚本使用不同的测试数据来执行,测试数据和测试行为完全分离, 这样的测试脚本设计模式称为数据驱动。(网盗结束)当我们测试某个网站的登录功能时,我们往往会使用不同的用户名和密码来验证登录模块对系统的影响,那么如果我们每一条数据都编写一条测试用例,这无疑是增加了代码量,代码重复,且显得那么臃肿(谁不喜欢身材好的呢?你懂的),这时候我们可以使用不同数据驱动代码执行相同的用例测试不同的场景。

实施数据驱动步骤

我们再来说说实施数据驱动测试的步骤:

1.创建/准备测试数据

2.封装读取数据的方法,保留测试脚本调用的接口/属性(我们需要传递给脚本什么参数)

3.编写自动化测试脚本

4.脚本中调用封装好的处理数据文件的模块并引入测试数据

5.执行测试脚本并分析测试结果

数据驱动测试环境准备

1.安装python3.x开发环境(能看到此文章的应该都有这个环境,没有的自行百度吧)

2.安装数据驱动模块ddt

安装方式1:cmd下执行命令 pip install ddt

安装方式2:https://pypi.org/simple/ddt/ 下载 并解压任意目录,cmd 运行命令python setup.py install

3.验证安装 pycharm 新建python文件并输入 import ddt 运行无报错信息既表示安装成功或者cmd 命令依次输入python回车 import ddt回车 无保存信息表示安装成功

4.unittest框架和ddt进行数据驱动

测试步骤

1.访问地址:https://mail.sohu.com/fe/#/login

2.输入用户名和密码

3.点击登录按钮

4.判断是否登录成功

数据存储

数据存在当前脚本中

数据准备

我们要实现的是用户登录的操作,所以用户名和密码是必须有的,期望结果可以有也可以没有。数据类型看源代码!

实例代码 

 from selenium import webdriver
from ddt import ddt, data, unpack
import unittest
import time
from selenium.common.exceptions import NoSuchWindowException
'''
简单数据驱动测试
'''
@ddt
class ddtTest(unittest.TestCase):
# 数据 可以是元祖, 列表, 字典(可迭代对象)
value = [['13691579846@sohu.com', 'xiaochao11520','https://mail.sohu.com/fe/#/homepage'],
['13691579844@sohu.com', 'xiaochao11520','https://mail.sohu.com/fe/#/homepage']]
# value = [{'uname':'******@sohu.com', 'password':'xiaochao11520','expected':'https://mail.sohu.com/fe/#/homepage'},
# {'uname':'******@sohu.com', 'password':'xiaochao11520','expected':'https://mail.sohu.com/fe/#/homepage'}]
def setUp(self):
self.testUrl = 'https://mail.sohu.com/fe/#/login'
self.driver = webdriver.Firefox()
self.driver.get(self.testUrl) @data(*value) # * 解析数据
@unpack# 用来解包, 将每组数据的第一个数据传递给uname依次类推, 当数据为字典时,形参需和字段的key值相同
def test_case1(self, uname, password, expected):
try:
username = self.driver.find_element_by_xpath("//input[@placeholder='请输入您的邮箱']")
username.send_keys(uname)
time.sleep(1)
userpassword = self.driver.find_element_by_xpath("//input[@placeholder='请输入您的密码']")
userpassword.send_keys(password)
self.driver.find_element_by_xpath("//input[@type='submit']").click()
time.sleep(2)
currenturl = self.driver.current_url
self.assertEqual(expected, currenturl,'登录失败')
except NoSuchWindowException as e:
print(e)
raise
except AssertionError:
print('期望值是{}, 实际值是{}'.format(expected,currenturl))
raise
except Exception:
raise
def tearDown(self):
self.driver.quit()
# pass
if __name__ == '__main__':
unittest.main()

简单数据驱动测试.py

源码分析

1.@ddt来装饰测试类(ddt数据驱动的规范写法,记住就ok)

2.@data(*value)装饰测试用例(也是一种规范,这边又涉及到装饰器,不懂的可以百度或者看我之前的文章又介绍,这边不再赘述,一句话两句话也说不清楚)记住:*value作用是打散数据,比如上面代码是用一个大列表存储两个小列表存放数据的,那么*value会得到两个小列表,每个小列表是一组测试数据

3.@unpack 解析*value数据,会把两个小列表里面的每一个数据取出来分别传递给我们测试用例的形参

方式1缺点

存储大量数据时,需查看源代码,不利于脚本的维护    

json文件读取测试数据进行数据驱动测试

数据准备

新建一个json文件(也可以是txt文件),将我们需要的两组测试数据以列表的形式写到json文件中,每组数据的每一项参数用相同的符号分割开(方便脚本读取数据)

实例代码

{
"value1":"******@sohu.com||xiaochao11520||https://mail.sohu.com/fe/#/homepage",
"value2":"******@sohu.com||xiaochao11520||https://mail.sohu.com/fe/#/homepage"
}

test_data.json

 from selenium import webdriver
from ddt import ddt, file_data
import unittest, time
from selenium.common.exceptions import NoSuchWindowException
import HTMLTestRunner
'''
从文件中读测试数据
''' @ddt # ddt装饰测试类
class Testdata(unittest.TestCase): def setUp(self):
self.driver = webdriver.Firefox()
self.driver.get('https://mail.sohu.com/fe/#/login') @file_data('test_data.json') # 读取文件的 文件中数据可以是一个列表,也可以是一个字典
def test_data(self,value):
uname, password, expected = tuple(value.strip().split('||')) # value是一个字符串
# print(type(value),value)
try:
username = self.driver.find_element_by_xpath("//input[@placeholder='请输入您的邮箱']")
username.send_keys(uname)
time.sleep(1)
userpassword = self.driver.find_element_by_xpath("//input[@placeholder='请输入您的密码']")
userpassword.send_keys(password)
self.driver.find_element_by_xpath("//input[@type='submit']").click()
time.sleep(2)
currenturl = self.driver.current_url
self.assertEqual(expected, currenturl,'登录失败')
except NoSuchWindowException as e:
raise e
except AssertionError:
print('期望值是{}, 实际值是{}'.format(expected,currenturl))
raise
except Exception:
raise def tearDown(self):
self.driver.quit()
if __name__ == '__main__':
unittest.main()
# import os
# from datetime import date
# currentPath = os.path.dirname(os.path.abspath(__file__))# 获取当前文件目录
# reportPath = os.path.join(currentPath,'report') # 创建一个report目录
# if not os.path.exists(reportPath):
# os.mkdir(reportPath) # 判断目录是否存在, 不存在就创建
# reportName = os.path.join(reportPath, str(date.today())+'report.html') # 拼接html报告
# with open(reportName,'wb') as f:
# suite = unittest.TestLoader().loadTestsFromTestCase(Testdata)
# runner = HTMLTestRunner.HTMLTestRunner(stream=f,verbosity=1, title='数据驱动测试报告', description='数据驱动')
# runner.run(suite)

使用数据文件驱动测试.py

源码分析

1.相对上个实例,这里使用了@file_data(文件路径), 参数必须是一个文件,这里是一个json文件, 数据可以是一个列表,也可以是一个字典

# 列表形式
[
"*******@sohu.com||xiaochao11520||https://mail.sohu.com/fe/#/homepage",
"*******@sohu.com||xiaochao11520||https://mail.sohu.com/fe/#/homepage"
]

2.测试用例接收的是一个字符串,需要对字符串进行处理,把用户名,密码,期望值解析出来

方式2优缺点

测试数据存在文件中,方便管理修改,添加数据,易于维护,缺点呢?emmm个人认为这种方式最好!

从xml读取数据进行数据驱动测试

数据准备

新建一个xml格式的文件,按照xml格式的语法需求,填写数据(xml文档我也不是很懂,简单的显示个文字啥的还可以^-^!)

<?xml version="1.0"?>
<bookList type="technolog">
<book>
<uname>******@sohu.com</uname>
<password>xiaochao11520</password>
<expected>https://mail.sohu.com/fe/#/homepage</expected>
</book>
<book>
<uname>******@sohu.com</uname>
<password>xiaochao11520</password>
<expected>https://mail.sohu.com/fe/#/homepage</expected>
</book>
</bookList>

xmlData.xml

实例代码

 from xml.etree import ElementTree

 class ParseXml(object):
def __init__(self, xmlpath):
self.xmlpath = xmlpath # 获取根节点
def getRoot(self):
tree = ElementTree.parse(self.xmlpath)
root = tree.getroot()
return root # 根据根节点查找子节点
def findNodeByName(self, parentNode, nodeName):
nodes = parentNode.findall(nodeName)
return nodes def getNodeOfChildText(self, node):
# 获取节点node下所有子节点的节点名作为key
# 本节点作为value组成的字典对象
childrenTextDict = {}
for i in list(node.iter())[1:]: # node 节点下的所有节点组成的列表
childrenTextDict[i.tag] = i.text
# print(list(node.iter())[1:])
return childrenTextDict # 获取节点node下面的节点的所有数据
def getDataFromXml(self, node):
root = self.getRoot()
books = self.findNodeByName(root, node)
dataList=[]
for book in books:
childrentext = self.getNodeOfChildText(book)
dataList.append(childrentext)
return dataList
if __name__=='__main__':
xml = ParseXml('./xmlData.xml')
root = xml.getRoot()
print(root.tag)
books = xml.findNodeByName(root, 'book') # 查找所有的book节点
for book in books:
# print(book[0].tag, book[0].text)
print(xml.getNodeOfChildText(book))
print(xml.getDataFromXml('book'))

doXML.py

 from dataDdt.doXML import ParseXml
from selenium import webdriver
from selenium.common.exceptions import NoSuchWindowException, TimeoutException
import unittest
from ddt import ddt, data,unpack
import time
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
values = ParseXml('./xmlData.xml')
@ddt
class xmltest(unittest.TestCase): def setUp(self):
self.driver = webdriver.Firefox()
self.driver.get('https://mail.sohu.com/fe/#/login')
@data(*values.getDataFromXml('book'))
@unpack
def test_xml(self,uname, password, expected):
try:
wait = WebDriverWait(self.driver,5)
wait.until(EC.element_to_be_clickable((By.XPATH, "//input[@type='submit']")))
username = self.driver.find_element_by_xpath("//input[@placeholder='请输入您的邮箱']")
username.send_keys(uname)
time.sleep(1)
userpassword = self.driver.find_element_by_xpath("//input[@placeholder='请输入您的密码']")
userpassword.send_keys(password)
self.driver.find_element_by_xpath("//input[@type='submit']").click()
time.sleep(2)
currenturl = self.driver.current_url
self.assertEqual(expected, currenturl, '登录失败')
except TimeoutException as e:
raise e
except NoSuchWindowException as e:
raise e
except AssertionError as e:
print('期望值是{}, 实际值是{}'.format(expected, currenturl))
raise e
except Exception:
raise
def tearDown(self):
self.driver.quit() if __name__=='__main__':
unittest.main()

从xml文件读取数据驱动测试.py

源码分析

1.xml文档编写(深入了解需百度)有点像html,但又有不同,xml中的节点可以是任意名称,每个节点同样是成双出现

2.增加了doXML.py文档,用来解析xml文件,方便脚本获取数据(注释写的很详细,不懂的化可以慢慢调试,哪里不懂print哪里)

3.测试脚本和上面的实例大致相同(不懂的加我qq直接问)

方式3优缺点

优点是做到了数据与测试的分离,方便数据维护,缺点也比较明显,需要对xml文档有一定的了解

总结

上面的数据驱动测试步骤是我自己总结的,看了上面的实例对于步骤应该还算合理,下面是我在网上找到的数据驱动测试步骤(感觉比较官方!大家可以参考)

1.编写测试脚本, 脚本需要支持从程序对象, 文件,或者数据库读入数据。(个人观点:如果脚本先编写完,测试数据还未准备,后期还要做修改)

2.将测试脚本使用的测试数据存入程序对象,文件,或者数据库等外部介质中。(个人观点:这个阶段实为准备数据的阶段,也就是我们数据要存在哪里,理应放在第一步)

3.运行脚本过程中,循环调用存储在外部介质中的测试数据。(个人观点:这里要考虑我们如何读取,使用数据)

4.验证所有的测试结果是否符合预期结果

ps:源码已经上传到我的git,地址:https://github.com/13691579846/WebdriverAPI 欢迎交流讨论QQ交流群:878565760

如何快速掌握DDT数据驱动测试?的更多相关文章

  1. 【python接口自动化】- DDT数据驱动测试

    简单介绍 ​ DDT(Date Driver Test),所谓数据驱动测试,简单来说就是由数据的改变从而驱动自动化测试的执行,最终引起测试结果的改变.通过使用数据驱动测试的方法,可以在需要验证多组数据 ...

  2. 【python】以souhu邮箱为例学习DDT数据驱动测试

    前言 DDT(Data-Driven Tests)是针对 unittest 单元测试框架设计的扩展库.允许使用不同的测试数据来运行一个测试用例,并将其展示为多个测试用例.通俗理解为相同的测试脚本使用不 ...

  3. python Unittest+excel+ddt数据驱动测试

    #!user/bin/env python # coding=utf- # @Author : Dang # @Time : // : # @Email : @qq.com # @File : # @ ...

  4. Python3|ddt|unittest|浅议数据驱动测试

    目录 1.DDT简介 2.data装饰器 3.unpack装饰器 4.file_data装饰器 5.总结 1.DDT简介 Data-Driven Tests(DDT)即数据驱动测试.它允许您通过不同的 ...

  5. python - 数据驱动测试 - ddt

    # -*- coding:utf-8 -*- ''' @project: jiaxy @author: Jimmy @file: study_ddt.py @ide: PyCharm Communit ...

  6. Python3-unittest测试框架之DDT数据驱动

    unittest测试框架之DDT数据驱动 ddt的使用 DDT数据驱动 DDT:Data Driver Test(数据驱动测试) 数据驱动思想:数据和用例进行分离,通过外部数据去生成测试用例 安装 p ...

  7. [ddt01篇]十年测试老鸟帮您解析:ddt数据驱动实现自动化测试入门基础应用

    一.什么是DDT数据驱动框架 ​ 全称:data driver test数据驱动测试框架,可以完美的应用于unittest框架实现数据驱动.ddt使用简介: 1.测试数据为多个字典的list类型 2. ...

  8. 基于Python的接口自动化-unittest测试框架和ddt数据驱动

    引言 在编写接口自动化用例时,我们一般针对一个接口建立一个.py文件,一条接口测试用例封装为一个函数(方法),但是在批量执行的过程中,如果其中一条出错,后面的用例就无法执行,还有在运行大量的接口测试用 ...

  9. 基于python的接口自动化测试+ddt数据驱动

    在测试接口时,一个接口会先写好测试用例,这个用例主要针对功能,传入参时考虑到各种场景,正常的,异常的,如:参数缺省,参数传一个六位数字写用例时考虑边界情况等. 一个接口设计用例时有可能会十几条到几十条 ...

随机推荐

  1. java里的堆内存于栈内存的区别

    这个区别对于我们来说并不大,这是内存分配的两种方法.一般代码逻辑,简单变量,结构体都是放入栈中,而对象,以及被装箱的数据是放入堆中的.简单来说,栈就是一个很长的栈(数据结构中的栈,如果不理解可以当做是 ...

  2. FMDB的简单实用

    一.FMDB 的框架引入点击此处去GitHub下载 二.FMDB 的优缺点 优点:使用起来更加面向对象,省去了很多麻烦.冗余的C语言代码:对比苹果自带的Core Data框架,更加轻量级和灵活:提供了 ...

  3. centos7搭建postfix邮件服务器

    在使用qq等邮件服务器厂商提供的邮件服务后,发现他们的邮件发送数量是有限制的,随着公司的业务的需求下,我们需要搭建一个邮件服务器,邮件服务器可以帮助我们在一些提醒方面和消息推送方面起到帮助. 理论性语 ...

  4. 阿里云和腾讯云免费SSL证书 专题

    阿里云部署SSL证书 http://www.cnblogs.com/sslwork/p/5984167.html 查找中间证书 为了确保兼容到所有浏览器,我们必须在阿里云上部署中间证书,如果不部署证书 ...

  5. 今天读一读七天学会NodeJS

    七天学会NODEJS NodeJS基础 小结 本章介绍了有关NodeJS的基本概念和使用方法,总结起来有以下知识点: NodeJS是一个JS脚本解析器,任何操作系统下安装NodeJS本质上做的事情都是 ...

  6. app后端设计(7)-- 项目管理

    移动互联网行业是个快速发展的行业,需求不断变化,产品更新快.基于移动互联网的以上特点,在开发产品的过程中,我们放弃了传统的瀑布流开发模型,引入了精益的理念和scrum这个敏捷开发框架,下面谈谈实施过程 ...

  7. B20J_2007_[Noi2010]海拔_平面图最小割转对偶图+堆优化Dij

    B20J_2007_[Noi2010]海拔_平面图最小割转对偶图+堆优化Dij 题意:城市被东西向和南北向的主干道划分为n×n个区域.城市中包括(n+1)×(n+1)个交叉路口和2n×(n+1)条双向 ...

  8. BZOJ_2662_[BeiJing wc2012]冻结_分层图最短路

    BZOJ_2662_[BeiJing wc2012]冻结_分层图最短路 Description “我要成为魔法少女!”     “那么,以灵魂为代价,你希望得到什么?” “我要将有关魔法和奇迹的一切, ...

  9. BZOJ_[JSOI2010]Group 部落划分 Group_kruskal

    BZOJ_[JSOI2010]Group 部落划分 Group_kruskal Description 聪聪研究发现,荒岛野人总是过着群居的生活,但是,并不是整个荒岛上的所有野人都属于同一个部落,野人 ...

  10. java 日期类 小结

    import java.text.*; import java.util.*; class Test2 { public static void main(String[] args) { Syste ...