项目目录
一.前言
1.相同的测试脚本使用不同的测试数据来执行,测试数据和测试行为完全分离, 这样的测试脚本设计模式称为数据驱动。
2.当测试某个网站的登录功能时,往往会使用不同的用户名和密码来验证登录模块对系统的影响,那么如果每一条数据都编写一条测试用例,这无疑是增加了代码量,代码重复,且显得那么臃肿,这时候可以使用不同数据驱动代码执行相同的用例测试不同的场景。
二.实施数据驱动步骤
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.判断是否登录成功
五.数据存储(不建议)
1.数据准备:要实现的是用户登录的操作,所以用户名和密码是必须有的,期望结果可以有也可以没有。
2.实例代码
简单数据驱动测试.py
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.Chrome()
self.driver.maximize_window()
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,'登录失败')
#print(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()
3.源码分析
3.1.@ddt来装饰测试类(ddt数据驱动的规范写法)。
3.2.@data(*value)装饰测试用例(也是一种规范)记住:value作用是打散数据,比如上面代码是用一个大列表存储两个小列表存放数据的,那么value会得到两个小列表,每个小列表是一组测试数据。
3.3.@unpack 解析*value数据,会把两个小列表里面的每一个数据取出来分别传递给测试用例的形参。
4.方式1缺点
4.1.存储大量数据时,需查看源代码,不利于脚本的维护。
六.json文件读取测试数据进行数据驱动测试(建议)
1.数据准备
1.1.新建json文件(也可以是txt文件),将我们需要的两组测试数据以列表的形式写到json文件中,每组数据的每一项参数用相同的符号分割开(方便脚本读取数据)。
2.实例代码
test_data.json
{
"value1":"13691579846@sohu.com||xiaochao11520||https://mail.sohu.com/fe/#/homepage",
"value2":"13691579844@sohu.com||xiaochao11520||https://mail.sohu.com/fe/#/homepage"
}
使用数据文件驱动测试.py
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.Chrome()
self.driver.maximize_window()
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,'登录失败')
#print(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__)) # 获取当前文件目录
print(currentPath)
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)
'''
3.源码分析
3.1.这里使用了@file_data(文件路径),参数必须是文件,这里是json文件,数据可以是列表,也可以是字典。
# 列表形式 [ "13691579846@sohu.com||xiaochao11520||https://mail.sohu.com/fe/#/homepage", "13691579844@sohu.com||xiaochao11520||https://mail.sohu.com/fe/#/homepage" ]
3.2.测试用例接收的是一个字符串,需要对字符串进行处理,把用户名,密码,期望值解析出来。
4.方式2优缺点
4.1.测试数据存在文件中,方便管理修改,添加数据,易于维护,个人认为这种方式最好!
HTMLTestRunner.py
"""
A TestRunner for use with the Python unit testing framework. It
generates a HTML report to show the result at a glance.
The simplest way to use this is to invoke its main method. E.g.
import unittest
import HTMLTestRunner
... define your tests ...
if __name__ == '__main__':
HTMLTestRunner.main()
For more customization options, instantiates a HTMLTestRunner object.
HTMLTestRunner is a counterpart to unittest's TextTestRunner. E.g.
# output to a file
fp = file('my_report.html', 'wb')
runner = HTMLTestRunner.HTMLTestRunner(
stream=fp,
title='My unit test',
description='This demonstrates the report output by HTMLTestRunner.'
)
# Use an external stylesheet.
# See the Template_mixin class for more customizable options
runner.STYLESHEET_TMPL = ''
# run the test
runner.run(my_test_suite)
------------------------------------------------------------------------
Copyright (c) 2004-2007, Wai Yip Tung
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name Wai Yip Tung nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
# URL: http://tungwaiyip.info/software/HTMLTestRunner.html
__author__ = "Wai Yip Tung"
__version__ = "0.8.2"
"""
Change History
Version 0.8.2
* Show output inline instead of popup window (Viorel Lupu).
Version in 0.8.1
* Validated XHTML (Wolfgang Borgert).
* Added description of test classes and test cases.
Version in 0.8.0
* Define Template_mixin class for customization.
* Workaround a IE 6 bug that it does not treat
%(heading)s
%(report)s
%(ending)s


