当前位置: 首页 > news >正文

Python自动化测试系列[v1.0.0][多种数据驱动实现附源码]

前情提要

请确保已经熟练掌握元素定位的常用方法及基本支持,请参考Python自动化测试系列[v1.0.0][元素定位]

数据驱动测试是自动化测试中一种重要的设计模式,这种设计模式可以将测试数据和测试代码分开,实现数据与代码解耦,与此同时还能够实现一次任务中使用不同的数据来执行执行相同的测试脚本,因此它会使得我们的代码层次结构清晰,容易维护,并且大大降低了代码量

数据驱动是自动化测试中非常常见的一种设计模式,应用的场景非常多,无论是在Web自动化还是在接口自动化、单元测试,亦或是在数据分析应用领域的测试上都会得到非常广泛的使用,常见的比如Web自动化的登录功能、一些录入类的功能,再比如接口入参、单元测试的入参,甚至在数据类应用的大量数据输入及结果比较上

使用Excel存储测试输入数据

数据文件

假如我们有如下一组数据存储在Excel里

序号检索词期望结果
1北京北京
2上海上海
3广州广州

获取测试数据方法

通过python的openpyxl模块解析Excel文件,并获取数据

安装openpyxl
C:\Users\Administrator>pip install openpyxl
Collecting openpyxlDownloading openpyxl-3.0.3.tar.gz (172 kB)|████████████████████████████████| 172 kB 384 kB/s
Collecting jdcalUsing cached jdcal-1.4.1-py2.py3-none-any.whl (9.5 kB)
Collecting et_xmlfileUsing cached et_xmlfile-1.0.1.tar.gz (8.4 kB)
Installing collected packages: jdcal, et-xmlfile, openpyxlRunning setup.py install for et-xmlfile ... doneRunning setup.py install for openpyxl ... done
Successfully installed et-xmlfile-1.0.1 jdcal-1.4.1 openpyxl-3.0.3

方法封装

# encoding = utf-8
from openpyxl import load_workbookclass ParseExcel(object):def __init__(self, excelPath, sheetName):self.wb = load_workbook(excelPath)#  self.sheet = self.lwb.get_sheet_by_name(sheetName)self.sheet = self.wb[sheetName]self.maxRowNum = self.sheet.max_rowdef getDatasFromSheet(self):dataList = []for line in list(self.sheet.rows)[1:]:tmpList = []tmpList.append(line[1].value)tmpList.append(line[2].value)dataList.append(tmpList)return dataListif __name__ == '__main__':excelPath = u'D:\\Programs\\Python\\PythonUnittest\\TestData\\测试数据.xlsx'sheetName = u'搜索数据表'pe = ParseExcel(excelPath, sheetName)for i in pe.getDatasFromSheet():print(i[0], i[1])

封装了getDatasFromSheet方法,该方法将解析Excel,并将数据存到List中去,后续的测试代码调用的实际上是从List里边获取数据

测试代码

# encoding = utf-8
from selenium import webdriver
import unittest
import time
import traceback
import ddt
import logging
from Util.ParseExcelUtil import ParseExcel
from selenium.common.exceptions import NoSuchElementException# 初始化日志对象
logging.basicConfig(# 日志级别level=logging.INFO,# 时间、代码所在文件名、代码行号、日志级别名字、日志信息format='%(asctime)s %(filename)s[line: %(lineno)d] %(levelname)s %(message)s',# 打印日志的时间datefmt='%a, %d %b %Y %H:%M:%S',# 日志文件存放的目录及日志文件名filename='D:\\Programs\\Python\\PythonUnittest\\Reports\\TestResults.TestResults',# 打开日志的方式filemode='w'
)excelPath = u"D:\\Programs\\Python\\PythonUnittest\\TestData\\测试数据.xlsx"
sheetName = u"搜索数据表"
excel = ParseExcel(excelPath, sheetName)@ddt.ddt
class TestDataDrivenByExcel(unittest.TestCase):def setUp(self):self.driver = webdriver.Chrome()@ddt.data( * excel.getDatasFromSheet())def test_dataDrivenByExcel(self, data):testData, expectData = tuple(data)url = "http://www.baidu.com"self.driver.get(url)self.driver.maximize_window()self.driver.implicitly_wait(10)try:self.driver.find_element_by_id("kw").send_keys(testData)self.driver.find_element_by_id("su").click()time.sleep(3)self.assertTrue(expectData in self.driver.page_source)except NoSuchElementException as e:logging.error(u"查找的页面元素不存在,异常堆栈信息为:" + str(traceback.format_exc()))except AssertionError as e:logging.info(u"搜索 ‘%s’,期望 ‘%s’ ,失败" % (testData, expectData))except Exception as e:logging.error(u"未知错误,错误信息:" + str(traceback.format_exc()))else:logging.info(u"搜索 ‘%s’,期望 ‘%s’ ,通过" % (testData, expectData))def tearDown(self):self.driver.quit()
if __name__ == "__main__":unittest.main()

使用Parameterize模块组织数据集作为测试输入数据

安装PARAMETERIZE

C:\Users\Administrator>pip install parameterized
Collecting parameterizedDownloading https://files.pythonhosted.org/packages/a3/bf/6ef8239028beae8298e0806b4f79c2466b1b16ca5b85dc13d631c5ea92c4/parameterized-0.7.1-py2.py3-none-any.whl
Installing collected packages: parameterized
Successfully installed parameterized-0.7.1

测试代码

# -*- coding: utf-8 -*-
# @Time: 4/27/2019 1:52 PM
# @Author : Yang DaWei
# @Project : DataDrivenTest
# @FileName: Unittest_Parameterized.py
import unittest
from selenium import webdriver
import time
from parameterized import parameterized
from selenium.common.exceptions import NoSuchElementException  # 引入NoSuchElementException异常类class LoginTest(unittest.TestCase):def setUp(self):self.driver = webdriver.Chrome()self.url = "http://mail.163.com"self.driver.implicitly_wait(10)def user_login_163(self, username, password):driver = self.driverdriver.get(self.url)# 定义frame,他是页面中的iframe控件frame = self.driver.find_element_by_xpath("//*[@id='loginDiv']/iframe")time.sleep(1)try:self.driver.switch_to.frame(frame)  # 切换进iframe控件self.driver.find_element_by_name("email").send_keys(username)  # 输入用户名self.driver.find_element_by_name("password").send_keys(password)  # 输入密码self.driver.find_element_by_id("dologin").click()  # 点击登陆按钮except NoSuchElementException as e:# 将未找到页面元素的异常记录进日志raise eexcept Exception as e:raise e@parameterized.expand([('', "davieyang", "请输入帐号"),("davieyang", '', "请输入密码"),("error", "error", "帐号或密码错误"),])def test_login(self, username, password, assert_text):self.user_login_163(username, password)message = self.driver.find_element_by_id("nerror").textself.assertEqual(message, assert_text)def tearDown(self):self.driver.quit()if __name__ == '__main__':unittest.main(verbosity=2)

使用JSON存储测试输入数据[List]

方式一

["北京||北京","上海||上海","广州||广州","深圳||深圳","香港||香港"
]
测试代码
# encoding = utf-8
"""
__title__ = ''
__author__ = 'davieyang'
__mtime__ = '2018/4/21'
"""
from selenium import webdriver
import unittest
import time
import logging
import traceback
import ddt
from selenium.common.exceptions import NoSuchElementException# 初始化日志对象
logging.basicConfig(# 日志级别level=logging.INFO,# 时间、代码所在文件名、代码行号、日志级别名字、日志信息format='%(asctime)s %(filename)s[line: %(lineno)d] %(levelname)s %(message)s',# 打印日志的时间datefmt='%a, %d %b %Y %H:%M:%S',# 日志文件存放的目录及日志文件名filename='F:\\DataDriven\\TestResults\TestResults.TestResults',# 打开日志的方式filemode='w'
)@ddt.ddt
class DataDrivenTestByDDTHTR(unittest.TestCase):def setUp(self):self.driver = webdriver.Chrome(executable_path="F:\\automation\\webdriver\\chromedriver.exe")# json文件所在路径@ddt.file_data("F:\\DataDriven\\testData\\test_data_list.json")def test_dataDrivenHTRByFile(self, value):url = "http://www.baidu.com"self.driver.get(url)self.driver.maximize_window()print(value)# 将从.json文件中读取出的数据用“||”分割成测试数据和期望的数据testdata, execptdata = tuple(value.strip().split("||"))# 设置隐式等待时间self.driver.implicitly_wait(10)try:self.driver.find_element_by_id("kw").send_keys(testdata)self.driver.find_element_by_id("su").click()time.sleep(3)# 断言期望结果是否出现在页面中self.assertTrue(execptdata in self.driver.page_source)except NoSuchElementException as e:logging.error(u"查找的页面元素不存在,异常堆栈信息为:" + str(traceback.format_exc()))except AssertionError as e:logging.info(u"搜索 '%s',期望 '%s' ,失败" % (testdata, execptdata))except Exception as e:logging.error(u"未知错误,错误信息:" + str(traceback.format_exc()))else:logging.info(u"搜索 '%s',期望 '%s' ,通过" % (testdata, execptdata))def tearDown(self):self.driver.quit()if __name__ == '__main__':unittest.main()

方式二

测试报告模板
# encoding = utf-8
"""
__title__ = 'DataDrivenTestByDDT use this template for generating testing report'
__author__ = 'davieyang'
__mtime__ = '2018/4/21'
"""
# encoding = utf-8
def htmlTemplate(trData):htmlStr = u'''<!DOCTYPE HTML><html><head><title>单元测试报告</title><style>body {width:80%;margin:40px auto;font-weight:bold;font-family: 'trebuchet MS', 'Lucida sans', SimSun;font-size:18px;color: #000;}table {* border-collapse:collapse;border-spacing:0;width:100%;}.tableStyle {/* border:solid #ggg 1px;*/border-style:outset;border-width:2px;/*border:2px;*/border-color:blue;}.tableStyle tr:hover {background: rgb(173.216.230);}.tableStyle td,.tableStyle th{border-left:solid 1px rgb(146,208,80);border-top:1px solid rgb(146,208,80);padding:15pxtext-align:center}.tableStyle th{padding:15px;background-color:rgb(146,208,80);/*表格标题栏设置渐变颜色*/background-image: -webkit -gradient(linear, left top, left bottom, from(#92D050), to(#A2D668))/*rgb(146,208,80)*/}     </style></head><body><center><h1>测试报告</h1></center><br /><table class="tableStyle"><thead><tr><th>Search Words</th><th>Assert Words</th><th>Start Time</th><th>Waste Time(s)</th><th>Status</th></tr></thead>'''endStr = u'''</table></body></html>'''html = htmlStr + trData + endStrprint(html)with open("D:\\\Programs\\\Python\\\PythonUnittest\\\Reports\\testTemplate.html", "wb") as fp:fp.write(html.encode("gbk"))
测试脚本
# encoding = utf-8
"""
__title__ = ''
__author__ = 'davieyang'
__mtime__ = '2018/4/21'
"""
from selenium import webdriver
import unittest
import time
import logging
import traceback
import ddt
from DataDrivenTest.ReportTemplate import htmlTemplate
from selenium.common.exceptions import NoSuchElementException# 初始化日志对象
logging.basicConfig(# 日志级别level=logging.INFO,# 时间、代码所在文件名、代码行号、日志级别名字、日志信息format='%(asctime)s %(filename)s[line: %(lineno)d] %(levelname)s %(message)s',# 打印日志的时间datefmt='%a, %d %b %Y %H:%M:%S',# 日志文件存放的目录及日志文件名filename='D:\\Programs\\Python\\PythonUnittest\\Reports\\TestResults.TestResults',# 打开日志的方式filemode='w'
)@ddt.ddt
class DataDrivenTestByDDT(unittest.TestCase):@classmethoddef setUpClass(cls):# 整个测试过程只调用一次DataDrivenTestByDDT.trStr = ""def setUp(self):self.driver = webdriver.Chrome(executable_path="D:\\Programs\\Python\\PythonUnittest\\BrowserDrivers\\chromedriver.exe")status = None  # 用于存放测试结果状态,失败‘fail’,成功‘pass’flag = 0  # 数据驱动测试结果的标志,失败置0,成功置1@ddt.file_data("D:\\Programs\\Python\\PythonUnittest\\TestData\\test_data_list.json")def test_dataDrivenByFile(self, value):# 决定测试报告中状态单元格中内容的颜色flagDict = {0: 'red', 1: '#00AC4E'}url = "http://www.baidu.com"self.driver.get(url)self.driver.maximize_window()print(value)# 从.json文件中读取出的数据用“||”分割成测试数据和期望的数据testdata, execptdata = tuple(value.strip().split("||"))# 设置隐式等待时间self.driver.implicitly_wait(10)try:# 获取当前的时间戳,用于后面计算查询耗时用start = time.time()# 获取当前时间的字符串,表示测试开始时间startTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())self.driver.find_element_by_id("kw").send_keys(testdata)self.driver.find_element_by_id("su").click()time.sleep(3)# 断言期望结果是否出现在页面中self.assertTrue(execptdata in self.driver.page_source)except NoSuchElementException as e:logging.error(u"查找的页面元素不存在,异常堆栈信息为:"+ str(traceback.format_exc()))status = 'fail'flag = 0except AssertionError as e:logging.info(u"搜索 ‘%s’,期望 ‘%s’ ,失败" %(testdata, execptdata))status = 'fail'flag = 0except Exception as e:logging.error(u"未知错误,错误信息:" + str(traceback.format_exc()))status = 'fail'flag = 0else:logging.info(u"搜索 ‘%s’,期望 ‘%s’ ,通过" %(testdata, execptdata))status = 'pass'flag = 1# 计算耗时,从将测试数据输入到输入框中到断言期望结果之间所耗时wasteTime = time.time() - start - 3  # 减去强制等待3秒# 每一组数据测试结束后,都将其测试结果信息插入表格行的HTML代码中,并将这些行HTML代码拼接到变量trStr变量中,# 等所有测试数据都被测试结束后,传入htmlTemplate()函数中,生成完整测试报告的HTML代码DataDrivenTestByDDT.trStr += u'''<tr><td>%s</td><td>%s</td><td>%s</td><td>%.2f</td><td style = "color: %s">%s</td></tr><br/>''' % (testdata, execptdata, startTime, wasteTime, flagDict[flag], status)def tearDown(self):self.driver.quit()@classmethoddef tearDownClass(cls):# 写自定义的HTML测试报告,整个过程只被调用一次htmlTemplate(DataDrivenTestByDDT.trStr)if __name__ == '__main__':unittest.main()
生成日志
Fri, 07 Dec 2018 15:05:36 DataDrivenTestByDDT.py[line: 81] INFO 搜索 ‘北京’,期望 ‘北京’ ,通过
Fri, 07 Dec 2018 15:05:50 DataDrivenTestByDDT.py[line: 81] INFO 搜索 ‘上海’,期望 ‘上海’ ,通过
Fri, 07 Dec 2018 15:06:04 DataDrivenTestByDDT.py[line: 81] INFO 搜索 ‘广州’,期望 ‘广州’ ,通过
Fri, 07 Dec 2018 15:06:18 DataDrivenTestByDDT.py[line: 81] INFO 搜索 ‘深圳’,期望 ‘深圳’ ,通过
Fri, 07 Dec 2018 15:06:32 DataDrivenTestByDDT.py[line: 81] INFO 搜索 ‘香港’,期望 ‘香港’ ,通过
HTML报告

在这里插入图片描述

使用JSON存储测试输入数据[字典]

除了在json文件中放置List类型的数据,还可以放置Dict类型的数据,在PO项目的TestData路径下新建一个文件,并命名为login.json,然后在文件中写入如下测试数据。

{"test_login_01": {"username":"","password":"davieyang","assert_text": "请输入帐号"},"test_login_02": {"username":"davieyang","password":"","assert_text": "请输入密码"},"test_login_03":{"username":"error","password":"error","assert_text": "帐号或密码错误"}
}

测试脚本

# -*- coding: utf-8 -*-
import unittest
from selenium import webdriver
from ddt import ddt, file_data
import time
# 引入NoSuchElementException异常类
from selenium.common.exceptions import NoSuchElementException
from Configuration import ConstantConfig
#  定义测试数据文件
login_json = ConstantConfig.jsondictdata@ddt
class TestLogin(unittest.TestCase):def setUp(self):self.driver = webdriver.Chrome()self.url = "http://mail.163.com"self.driver.implicitly_wait(10)def user_login_163(self, username, password):driver = self.driverdriver.get(self.url)# 定义frame,他是页面中的iframe控件frame = self.driver.find_element_by_xpath("//*[@id='loginDiv']/iframe")time.sleep(1)try:self.driver.switch_to.frame(frame)  # 切换进iframe控件self.driver.find_element_by_name("email").send_keys(username)  # 输入用户名self.driver.find_element_by_name("password").send_keys(password)  # 输入密码self.driver.find_element_by_id("dologin").click()  # 点击登陆按钮except NoSuchElementException as e:# 将未找到页面元素的异常记录进日志raise eexcept Exception as e:raise e@file_data(login_json)def test_login(self, username, password, assert_text):  # 定义测试方法self.user_login_163(username, password)  # 调用登陆163的方法message = self.driver.find_element_by_id("nerror").text  self.assertEqual(message, assert_text)  # 断言def tearDown(self):self.driver.quit()
if __name__ == '__main__':unittest.main(verbosity=2)

使用MySQL存储测试输入数据

测试数据

# encoding = utf-8create_database = 'CREATE DATABASE IF NOT EXISTS davieyang DEFAULT CHARSET utf8 COLLATE utf8_general_ci;'
drop_table = 'DROP TABLE testdata;'
create_table = """CREATE TABLE testdata(ID int primary key not null auto_increment comment '主键',BOOKNAME varchar(40) unique not null comment '书名',AUTHOR varchar(30) not null comment '作者')engine = innodb character set utf8 comment '测试数据表';
"""

获取数据库测试数据方法

# encoding = utf-8
"""
__title__ = ''
__author__ = 'davieyang'
__mtime__ = '2018/4/21'
"""
import pymysql
from TestData.SqlScripts import create_table
from TestData.SqlScripts import create_database
from TestData.SqlScripts import drop_tableclass MySQL(object):def __init__(self, host, port, dbName, username, password, charset):self.conn = pymysql.connect(host=host,port=port,db=dbName,user=username,password=password,charset=charset)self.cur = self.conn.cursor()def create(self):try:self.cur.execute(create_database)self.conn.select_db("davieyang")self.cur.execute(drop_table)self.cur.execute(create_table)'''cur.execute("drop database if exists davieyang")   #如果davieyang数据库存在则删除  cur.execute("create database davieyang")   #新创建一个数据库davieyang  cur.execute("use davieyang")         #选择davieyang这个数据库  # sql 中的内容为创建一个名为testdata的表  sql = """create table testdata(id BIGINT,name VARCHAR(20),age INT DEFAULT 1)"""  #()中的参数可以自行设置  conn.execute("drop table if exists testdata") # 如果表存在则删除  conn.execute(sql)# 创建表    # 删除  # conn.execute("drop table testdata")  conn.close()# 关闭游标连接  connect.close()# 关闭数据库服务器连接 释放内存  '''except pymysql.Error as e:raise eelse:self.cur.close()self.conn.commit()self.conn.close()print(u"创建数据库和表成功")def insertDatas(self):try:sql = "insert into testdata(bookname, author) values(%s, %s);"self.cur.executemany(sql, [('selenium xml DataDriven', 'davieyang'),('selenium excel DataDriven', 'davieyang'),('selenium ddt data list', 'davieyang')])except pymysql.Error as e:raise eelse:self.conn.commit()print(u"初始数据插入成功")self.cur.execute("select * from testData;")for i in self.cur.fetchall():print(i[1], i[2])self.cur.close()self.conn.close()def getDataFromDataBase(self):# 从数据库中获取数据# bookname作为搜索关键词,author作为期望结果self.cur.execute("select bookname, author from testdata;")# 从查询区域取回所有查询结果dataTuple = self.cur.fetchall()return dataTupledef closeDataBase(self):# 数据库清理self.cur.close()self.conn.commit()self.conn.close()if __name__ == "__main__":db = MySQL(host="localhost",port=3306,dbName="davieyang",username="root",password="root",charset="utf8")print(db.getDataFromDataBase())db.closeDataBase()

测试脚本

# encoding = utf-8
"""
__title__ = ''
__author__ = 'davieyang'
__mtime__ = '2018/4/21'
"""
from selenium import webdriver
import unittest
import time
import logging
import traceback
import ddt
from Util.MysqlDBUtil import MySQL
from selenium.common.exceptions import NoSuchElementException# 初始化日志对象
logging.basicConfig(# 日志级别level=logging.INFO,# 时间、代码所在文件名、代码行号、日志级别名字、日志信息format='%(asctime)s %(filename)s[line: %(lineno)d] %(levelname)s %(message)s',# 打印日志的时间datefmt='%a, %d %b %Y %H:%M:%S',# 日志文件存放的目录及日志文件名filename='F:\\DataDriven\\TestResults\TestResults.TestResults',# 打开日志的方式filemode='w'
)def getTestDatas():db = MySQL(host="localhost",port=3306,dbName="davieyang",username="root",password="root",charset="utf8")# 从数据库中获取测试数据testData = db.getDataFromDataBase()db.closeDataBase()return testData@ddt.ddt
class DataDrivenByMySQL(unittest.TestCase):def setUp(self):self.driver = webdriver.Chrome(executable_path=r"F:\automation\webdriver\chromedriver.exe")@ddt.data(* getTestDatas())def test_dataDrivenByMySQL(self, data):# 对获得的数据进行解包testData, expectData =dataurl = "http://www.baidu.com"self.driver.get(url)self.driver.maximize_window()print(testData, expectData)self.driver.implicitly_wait(10)try:self.driver.find_element_by_id("kw").send_keys(testData)self.driver.find_element_by_id("su").click()time.sleep(3)self.assertTrue(expectData in self.driver.page_source)except NoSuchElementException as e:logging.error(u"查找的页面元素不存在,异常堆栈信息为:" + str(traceback.format_exc()))except AssertionError as e:logging.info(u"搜索 ‘%s’,期望 ‘%s’ ,失败" % (testData, expectData))except Exception as e:logging.error(u"未知错误,错误信息:" + str(traceback.format_exc()))else:logging.info(u"搜索 ‘%s’,期望 ‘%s’ ,通过" % (testData, expectData))def tearDown(self):self.driver.quit()if __name__ == "__main__":unittest.main()
# encoding = utf-8
"""
__title__ = ''
__author__ = 'davieyang'
__mtime__ = '2018/4/21'
"""
from selenium import webdriver
import unittest
import time
import logging
import traceback
import ddt
from selenium.common.exceptions import NoSuchElementException# 初始化日志对象
logging.basicConfig(# 日志级别level=logging.INFO,# 时间、代码所在文件名、代码行号、日志级别名字、日志信息format='%(asctime)s %(filename)s[line: %(lineno)d] %(levelname)s %(message)s',# 打印日志的时间datefmt='%a, %d %b %Y %H:%M:%S',# 日志文件存放的目录及日志文件名filename='F:\\DataDriven\\TestResults\TestResults.TestResults',# 打开日志的方式filemode='w'
)@ddt.ddt
class DataDrivenDDT(unittest.TestCase):def setUp(self):self.driver = webdriver.Chrome(executable_path="F:\\automation\\webdriver\\chromedriver.exe")@ddt.data([u"阿里巴巴", u"腾讯"], [u"美团外卖", u"百度"], [u"饿了么", u"蚂蚁金服"])@ddt.unpackdef test_dataDrivenByDDT(self, testdata, expectdata):url = "http://www.baidu.com"self.driver.get(url)self.driver.implicitly_wait(30)try:self.driver.find_element_by_id("kw").send_keys(testdata)self.driver.find_element_by_id("su").click()time.sleep(3)self.assertTrue(expectdata in self.driver.page_source)except NoSuchElementException as e:logging.error(u"查找的页面元素不存在,异常堆栈信息:" + str(traceback.format_exc()))except AssertionError as e:logging.info(u"搜索 '%s',期望 '%s' ,失败" % (testdata, expectdata))except Exception as e:logging.error(u"未知错误,错误信息:" + str(traceback.format_exc()))else:logging.info(u"搜索 '%s',期望 '%s' ,通过" % (testdata, expectdata))def tearDown(self):self.driver.quit()if __name__ == '__main__':unittest.main()

使用XML存储测试输入数据

<?xml version = "1.0" encoding = "utf-8"?>
<bookList type = "technology"><book><name>selenium xml datadriven</name><author>davieyang</author></book><book><name>selenium excel datadriven</name><author>davieyang</author></book><book><name>selenium ddt data list</name><author>davieyang</author></book>
</bookList>

解析XML方法

# encoding = utf-8
"""
__title__ = ''
__author__ = 'davieyang'
__mtime__ = '2018/4/21'
"""
from xml.etree import ElementTreeclass ParseXML(object):def __init__(self, xmlPath):self.xmlPath = xmlPathdef getRoot(self):# 打开将要解析的XML文件tree = ElementTree.parse(self.xmlPath)# 获取XML文件的根节点对象,然后返回给调用者return tree.getroot()def findNodeByName(self, parentNode, nodeName):# 通过节点的名字获取节点对象nodes = parentNode.findall(nodeName)return nodesdef getNodeofChildText(self, node):# 获取节点node下所有子节点的节点名作为key,本节点作为value组成的字典对象childrenTextDict = {i.tag: i.text for i in list(node.iter())[1:]}# 上面代码等价于'''childrenTextDict = {}for i in list(node.iter())[1:]:fhildrenTextDict[i.tag] = i.text'''return childrenTextDictdef getDataFromXml(self):# 获取XML文档的根节点对象root = self.getRoot()# 获取根节点下所有名为book的节点对象books = self.findNodeByName(root, "book")dataList = []# 遍历获取到的所有book节点对象# 取得需要的测试数据for book in books:childrenText = self.getNodeofChildText(book)dataList.append(childrenText)return dataListif __name__ == "__main__":xml = ParseXML(r"F:\seleniumWithPython\TestData\TestData.xml")datas = xml.getDataFromXml()for i in datas:print(i["name"], i["author"])

测试脚本

# encoding = utf-8
"""
__title__ = ''
__author__ = 'davieyang'
__mtime__ = '2018/4/21'
"""
from selenium import webdriver
import unittest
import time
import logging
import traceback
import ddt
from Util.ParseXMLUtil import ParseXML
from selenium.common.exceptions import NoSuchElementException# 初始化日志对象
logging.basicConfig(# 日志级别level=logging.INFO,# 时间、代码所在文件名、代码行号、日志级别名字、日志信息format='%(asctime)s %(filename)s[line: %(lineno)d] %(levelname)s %(message)s',# 打印日志的时间datefmt='%a, %d %b %Y %H:%M:%S',# 日志文件存放的目录及日志文件名filename='D:\\Programs\\Python\\PythonUnittest\\Reports\\TestResults.TestResults',# 打开日志的方式filemode='w'
)# currentPath = os.path.dirname(os.path.abspath(__file__))
# dataFilePath = os.path.join(currentPath, "TestData.xml")
dataFilePath = "D:\\Programs\\Python\\PythonUnittest\\TestData\\TestData.xml"
print(dataFilePath)# 创建ParseXML类实例对象
xml = ParseXML(dataFilePath)@ddt.ddt
class DataDrivenTestByXML(unittest.TestCase):def setUp(self):self.driver = webdriver.Chrome(executable_path=r"F:\automation\webdriver\chromedriver.exe")@ddt.data(* xml.getDataFromXml())def test_dataDrivenByXML(self, data):testData, expectData = data["name"], data["author"]url = "http://www.baidu.com"self.driver.get(url)self.driver.maximize_window()self.driver.implicitly_wait(10)try:self.driver.find_element_by_id("kw").send_keys(testData)self.driver.find_element_by_id("su").click()time.sleep(3)self.assertTrue(expectData in self.driver.page_source)except NoSuchElementException as e:logging.error(u"查找的页面元素不存在,异常堆栈信息为:" + str(traceback.format_exc()))except AssertionError as e:logging.info(u"搜索 ‘%s’,期望 ‘%s’ ,失败" % (testData, expectData))except Exception as e:logging.error(u"未知错误,错误信息:" + str(traceback.format_exc()))else:logging.info(u"搜索 ‘%s’,期望 ‘%s’ ,通过" % (testData, expectData))def tearDown(self):self.driver.quit()if __name__ == "__main__":unittest.main()

相关文章:

Python自动化测试系列[v1.0.0][多种数据驱动实现附源码]

前情提要 请确保已经熟练掌握元素定位的常用方法及基本支持&#xff0c;请参考Python自动化测试系列[v1.0.0][元素定位] 数据驱动测试是自动化测试中一种重要的设计模式&#xff0c;这种设计模式可以将测试数据和测试代码分开&#xff0c;实现数据与代码解耦&#xff0c;与此同…...

【论文笔记】Gemini: A Family of Highly Capable Multimodal Models——细看Gemini

Gemini 【一句话总结&#xff0c;对标GPT4&#xff0c;模型还是transformer的docoder部分&#xff0c;提出三个不同版本的Gemini模型&#xff0c;Ultra的最牛逼&#xff0c;Nano的可以用在手机上。】 谷歌提出了一个新系列多模态模型——Gemini家族模型&#xff0c;包括Ultra…...

iOS加密CoreML模型

生成模型加密密钥 必须在Xcode的Preferences的Accounts页面登录Apple ID&#xff0c;才能在Xcode中生成模型加密密钥。 在Xcode中打开模型&#xff0c;单击Utilities选项卡&#xff0c;然后单击“Create Encryption Key”按钮。 从下拉菜单中选择当前App的Personal Team&…...

Springboot自定义start首发预告

Springboot自定义start首发预告 基于Springboot的自定义start , 减少项目建设重复工作, 如 依赖 , 出入参包装 , 日志打印 , mybatis基本配置等等等. 优点 模块化 可插拔 易于维护和升级 定制化 社区支持(后期支持) 发布时间 预告: 2023-12-10 预计发布: 2024-1-1 , 元旦首…...

[GWCTF 2019]我有一个数据库1

提示 信息收集phpmyadmin的版本漏洞 这里看起来不像是加密应该是编码错误 这里访问robots.txt 直接把phpinfo.php放出来了 这里能看到它所有的信息 这里并没有能找到可控点 用dirsearch扫了一遍 ####注意扫描buuctf的题需要控制扫描速度&#xff0c;每一秒只能扫10个多一个都…...

【LeetCode每日一题】1904. 你完成的完整对局数

给你两个字符串 startTime 和 finishTime &#xff0c;均符合 "HH:MM" 格式&#xff0c;分别表示你 进入 和 退出 游戏的确切时间&#xff0c;请计算在整个游戏会话期间&#xff0c;你完成的 完整对局的对局数 。 如果 finishTime 早于 startTime &#xff0c;这表示…...

+0和不+0的性能差异

前几日&#xff0c;有群友转发了某位技术大佬的weibo。并在群里询问如下两个函数哪个执行的速度比较快&#xff08;weibo内容&#xff09;。 func g(n int, ch chan<- int) {r : 0for i : 0; i < n; i {r i}ch <- r 0 }func f(n int, ch chan<- int) {r : 0for …...

美颜技术讲解:视频美颜SDK的开发与集成

如今&#xff0c;美颜技术的应用愈发成为吸引用户的一项重要功能。本文将深入探讨视频美颜SDK的开发与集成&#xff0c;揭示其背后的技术原理和实现步骤。 一、美颜技术的背后 美颜技术并非仅仅是简单的滤镜效果&#xff0c;而是一项涉及复杂图像处理和算法的技术。在视频美颜…...

期末数组函数加强练习

前言&#xff1a;由于时间问题&#xff0c;部分题解取自网友&#xff0c;但都是做过的好题。 对于有些用c实现的题目&#xff0c;可以转化成c实现&#xff0c;cin看成c的读入&#xff0c;可以用scanf&#xff0c;输出cout看作printf&#xff0c;endl即换行符 开胃菜&#xff…...

如何下载B站视频?我来教你B站视频下载方法

如何下载B站视频&#xff1f;B站作为一个巨大的宝藏库&#xff0c;日常可以拿它作为娱乐工具&#xff0c;刷一些有趣新奇的短视频。也可以把它作为一款成长学习工具&#xff0c;具有丰富的公开课、纪录片内容。 对于较短的视频来说&#xff0c;花费几分钟时间看一下就结束了&am…...

AcWing 3709:单链表节点交换 ← 四川大学考研机试题

【题目来源】 https://www.acwing.com/problem/content/3712/【题目描述】 输入一个单链表&#xff0c;依次交换前2个数&#xff0c;第3、4个数&#xff0c;第5、6个数&#xff0c;…&#xff0c;以此类推&#xff0c;直到操作完整个链表。 如果链表长度是奇数&#xff0c;则最…...

RocketMQ源码 Broker-ConsumerFilterManager 消费者数据过滤管理组件源码分析

前言 ConsumerFilterManager 继承了ConfigManager配置管理组件&#xff0c;拥有将内存数据持久化到磁盘文件consumerFilter.json的能力。它主要负责&#xff0c;对在消费者拉取消息时&#xff0c;进行消息数据过滤&#xff0c;且只针对使用表达式过滤的消费者有效。 源码版本&…...

数据挖掘-07-航空公司客户价值分析(包括数据和代码)

文章目录 0. 数据代码下载1. 背景与挖掘目标2. 导入相关库&#xff0c;加载数据2.1客户基本信息分布a. 绘制会员性别比例饼图b. 绘制会员各级别人数条形图c. 绘制年龄分布图 2.2 客户乘机信息分布分析a. 绘制客户飞行次数箱线图b. 绘制客户总飞行公里数箱线图 2.3 客户积分信息…...

浏览器 css 默认的字体图表

以下是一些常见的浏览器&#xff08;PC端&#xff09;中网站 CSS 默认字体及其对应的字体系列&#xff08;font family&#xff09;&#xff1a; 浏览器默认字体字体系列&#xff08;font family&#xff09;ChromeArial, sans-serif“Arial”, “Helvetica Neue”, Helvetica…...

JAVA:注册表窗口的实现

目录 题目要求&#xff1a; 思路大意&#xff1a; 窗体的实现&#xff1a; 窗口A&#xff1a; 窗口B&#xff1a; 窗体之间的构思&#xff1a; 关键代码的实现&#xff1a; 窗口A&#xff1a; 封装列表&#xff1a; 窗口B&#xff1a; 题目要求&#xff1a; 使用…...

Liunx Centos 防火墙操作

liunx centos 防火墙 查看防火墙状态 systemctl status firewalld查看已经开放的端口 firewall-cmd --list-ports添加端口3306 firewall-cmd --zonepublic --add-port3306/tcp --permanent重启防火墙 firewall-cmd --reload数据库开放账号可以外网登陆 mysql -u root -p …...

VirtualBox 和 Vagrant 快速安装 Centos7 报错

VirtualBox 和 Vagrant 快速安装 Centos7 报错 今天尝试用 VirtualBox 和 Vagrant 快速安装 Centos7&#xff0c;BUG 多多&#xff01; 1&#xff09;下载 6.1.26 版本 VirtualBox&#xff0c;Windows11 不兼容&#xff1f;&#xff1f;&#xff1f;什么鬼&#xff1f; 解决…...

使用Python进行数学四则运算

当我们讨论到Python中的计算问题时&#xff0c;我们必然涉及到加法运算符&#xff08;&#xff09;、减法运算符&#xff08;-&#xff09;、乘法运算符&#xff08;*&#xff09;以及除法运算符&#xff08;/&#xff09;这四大常见的算术运算。下面&#xff0c;我将为您展示如…...

成都工业学院2021级操作系统专周课程设计FCFS,SSTF,SCAN,LOOK算法的实现

运行环境 操作系统&#xff1a;Windows 11 家庭版 运行软件&#xff1a;CLion 2023.2.2 源代码文件 #include <iostream> #include <vector> #include <algorithm> #include <random> using namespace std;// 生成随机数 int generateRandomNumber…...

【51单片机系列】矩阵按键扩展实验

本文对矩阵按键的一个扩展&#xff0c;利用矩阵按键和动态数码管设计一个简易计算器。代码参考&#xff1a;https://blog.csdn.net/weixin_47060099/article/details/106664393 实现功能&#xff1a;使用矩阵按键&#xff0c;实现一个简易计算器&#xff0c;将计算数据及计算结…...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分&#xff1a; 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析&#xff1a; CTR…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

【Java学习笔记】Arrays类

Arrays 类 1. 导入包&#xff1a;import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序&#xff08;自然排序和定制排序&#xff09;Arrays.binarySearch()通过二分搜索法进行查找&#xff08;前提&#xff1a;数组是…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...