自动化测试框架-数据驱动(2)
5、使用Excel进行数据驱动测试
测试逻辑:
(1)打开百度首页,从Excel文件中读取测试数据作为搜索关键词
(2)在搜索输入框中输入读取出搜索关键词
(3)单击搜索按钮
(4)断言搜索结果页面中是否出Excel文件中提供的预期内容,包含则认为测试执行成功,否则认为失败
测试数据准备:
在本地磁盘D:\test\DataDrivenTesting目录中新建一个“测试数据.xlsx”,工作表名为“搜索数据表”,内容如下“
序号 搜索词 期望结果
1 邓肯 蒂姆
2 乔丹 迈克尔
3 库里 斯蒂芬
实例代码:
在Pycharm中新建一个ExcelDataDrivenProject的Python工程,工程下新建两个文件,文件名分别为ExcelUtil.py和DataDrivenByExcel.py和DataDrivenByExcel.py
ExcelUtil.py文件用于编写读取Excel的脚本,具体内容如下:
#encoding=utf-8 from openpyxl import load_workbook class ParseExcel(object): def __init__(self, excelPath, sheetName): # 将要读取的excel加载到内存 self.wb = load_workbook(excelPath) # 通过工作表名称获取一个工作表对象 self.sheet = self.wb.get_sheet_by_name(sheetName) # 获取工作表中存在数据的区域的最大行号 self.maxRowNum = self.sheet.max_row def getDatasFromSheet(self): # 用于存放从工作表中读取出来的数据 dataList = [] for line in self.sheet.rows: # 遍历工作表中数据区域的每一行, # 并将每行中各个单元格的数据取出存于列表tmpList中, # 然后再将存放一行数据的列表添加到最终数据列表dataList中 tmpList = [] tmpList.append(line[1].value) tmpList.append(line[2].value) dataList.append(tmpList) # 将获取工作表中的所有数据的迭代对象返回 # 因为工作表中的第一行是标题行,所以需要去掉 return dataList[1:] if __name__ == '__main__': excelPath = u'D:\\test\\DataDrivenTesting\\测试数据.xlsx' sheetName = u"搜索数据表" pe = ParseExcel(excelPath, sheetName) print pe.getDatasFromSheet() for i in pe.getDatasFromSheet(): print i[0], i[1]
DataDrivenByExcel.py文件用于编写数据驱动测试脚本代码,具体内容如下:
#encoding=utf-8 import unittest,time import logging,traceback import ddt from selenium import webdriver from selenium.common.exceptions import NoSuchElementException from ExcelUtil import ParseExcel #初始化日志对象 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:\\test\\DataDrivenTesting\\report.log", #打开日志文件的方式 filemode = "w" ) excelPath = u"D:\\test\\DataDrivenTesting\\测试数据.xlsx" sheetName = u"搜索数据表" #ParseExcel类的实例对象 excel = ParseExcel(excelPath,sheetName) @ddt.ddt class TestDemo(unittest.TestCase): def setUp(self): self.driver = webdriver.Ie(executable_path = "D:\\IEDriverServer") @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() #设置隐式等待时间为10秒 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,e: logging.error(u"查找的页面元素不存在,异常堆栈信息:"+str(traceback.format_exc())) except AssertionError, e: #注意引号格式 logging.info(u"搜索“%s”,期望“%s”,失败" % (testdata, expectdata)) except Exception, 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()
不使用ddt和uniitest的Excel数据驱动,DataDrivenByExcel.py:
#encoding=utf-8 from selenium import webdriver import time import datetime from openpyxl import * wb = load_workbook(u"D:\\test\\DataDrivenTesting\\测试数据.xlsx") ws = wb.active #获取第一个sheet print u"最大行号:", ws.max_row driver = webdriver.Ie(executable_path = "D:\\IEDriverServer") test_result = [] #Excel的行是从1开始的,所以我们从第二行开始遍历(第一行是标题) #且使用切片时,必须有结束行的索引号,不能写成[1:],这样会报错 #Excel的列号是从0开始的,列读取以出来后是一个元组 for row in ws[2:ws.max_row]: print row[1],row[2] try: driver.get("http://www.baidu.com") driver.find_element_by_id("kw").send_keys(row[1].value) driver.find_element_by_id("su").click() time.sleep(3) assert row[2].value in driver.page_source row[3].value = time.strftime("%Y-%m-%d %H:%M:%S") row[4].value = u"成功" except AssertionError,e: row[3].value = time.strftime("%Y-%m-%d %H:%M:%S") row[4].value = u"断言失败" except Exception,e: row[3].value = time.strftime("%Y-%m-%d %H:%M:%S") row[4].value = u"出现异常失败" driver.quit() wb.save(u"D:\\test\\DataDrivenTesting\\测试数据.xlsx")
6、使用XML进行数据驱动测试
测试逻辑:
(1)打开百度首页,从XML文件中读取测试数据作为搜索关键词
(2)在搜索框中输入读取出的搜索关键词
(3)单击搜索按钮
(4)断言搜索结果页面中是否出现了XML文件中提供的预期内容,包含则认为测试执行成功,否则认为失败
实例代码:
在PyCharm中新建一个名叫XMLDataDrivenProject的Python工程,并在工程下新建三个文件,文件名分别为XmlUtil.py、TestData.xml以及DataDrivenByXML.py
TestData.xml文件用于存放测试数据,具体内容如下:
<?xml version = "1.0" encoding = "utf-8"?> <bookList type = "technology"> <book> <name> Selenium WebDriver 实战宝典</name> <author>吴晓华</author> </book> <book> <name> HTTP 权威指南</name> <author>古尔利</author> </book> <book> <name>探索式软件测试</name> <author>惠特克</author> </book> </bookList>
XmlUtil.py文件用于解析xmlutil.py文件,获取测试数据,具体内容如下:
#encoding=utf-8 from xml.etree import ElementTree class ParseXML(object): def __init__(self,xmlPath): self.xmlPath = xmlPath def getRoot(self): #打开将要解析的XML文件 tree = ElementTree.parse(self.xmlPath) #获取XML文件的根节点对象,也就是树的根,然后返回给调用者 return tree.getroot() def findNodeByName(self,parentNode,nodeName): #通过节点的名字,获取节点对象 nodes = parentNode.findall(nodeName) return nodes def getNodeOfChildText(self,node): #获取节点node下所有子节点的节点名作为key,本节点作为value组成的字典对象 childrenTextDick = {i.tag:i.text for i in list(node.iter())[1:]} #上面代码造价于下面代码 """ childrenTextDick = {} for i in list(node.iter())[1:]: childrenTextDick[i.tag] = i.text """ return childrenTextDick def 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 dataList if __name__ == "__main__": xml = ParseXML(r"D:\\PythonProject\\XMLDataDrivenProject\\TestData.xml") datas = xml.getDataFromXml() for i in datas: print i["name"],i["author"]
DataDrivenByXml.py文件用于编写数据驱动测试脚本,具体内容如下:
#encoding=utf-8 from selenium import webdriver import unittest,time,os import logging,traceback import ddt from XmlUtil 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:\\test\\DataDrivenTesting\\report.log", #打开日志文件的方式 filemode = "w" ) #获取当前文件所在父目录的绝对路径 currentPath = os.path.dirname(os.path.abspath(__file__)) #获取数据文件的绝对路径 dataFilePath = os.path.join(currentPath,"TestData.xml") print dataFilePath #创建ParseXML类实例对象 xml = ParseXML(dataFilePath) @ddt.ddt class TestDemo(unittest.TestCase): def setUp(self): self.driver = webdriver.Ie(executable_path = "D:\\IEDriverServer") @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() print testdata,expectdata #设置隐式等待时间为10秒 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,e: logging.error(u"查找的页面元素不存在,异常堆栈信息:"+str(traceback.format_exc())) except AssertionError, e: #注意引号格式 logging.info(u"搜索“%s”,期望“%s”,失败" % (testdata, expectdata)) except Exception, 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()
7、使用MySQL数据库进行数据驱动测试
测试逻辑:
(1)打开百度首页,从MySql数据库中获取测试过程中需要的测试数据
(2)在搜索输入框中输入查询关键词测试数据
(3)单击搜索按钮
(4)断言搜索结果页面中是否出现数据库中提供的预期内容,包含则认为测试执行成功,否则认为失败
环境准备:
安装MySql
实例代码:
在PyCharm中新建一个名叫DataBaseDataDrivenProject的Python工程,并在工程下新建四个文件,文件名分别为Sql.py、DataBaseInit.py、MysqlUtil.py和DataDrivenByMySql.py
Sql.py文件用于编写创建数据库及数据表的Sql语句,具体内容如下:
#encoding=utf-8 # 创建gloryroad数据库sql语句 create_database = 'CREATE DATABASE IF NOT EXISTS gloryroad DEFAULT CHARSET utf8 COLLATE utf8_general_ci;' # 创建testdata表 create_table = """ drop table if exists testdata; create table testdata( id int not null auto_increment comment '主键', bookname varchar(40) unique not null comment '书名', author varchar(30) not null comment '作者', test_result varchar(30) default null, primary key(id) )engine=innodb character set utf8 comment '测试数据表'; """
DataBaseInit.py文件用于编写初始化数据库的脚本,具体内容如下:
#encoding=utf-8 import MySQLdb from Sql import * class DataBaseInit(object): # 本类用于完成初始化数据操作 # 创建数据库,创建数据表,向表中插入测试数据 def __init__(self, host, port, dbName, username, password, charset): self.host = host self.port = port self.db = dbName self.user = username self.passwd = password self.charset = charset def create(self): try: # 连接mysql数据库 conn = MySQLdb.connect( host = self.host, port = self.port, user = self.user, passwd = self.passwd, charset = self.charset ) # 获取数据库游标 cur = conn.cursor() # 创建数据库 cur.execute(create_database) # 选择创建好的gloryroad数据库 conn.select_db("gloryroad") # 创建测试表 cur.execute(create_table) except MySQLdb.Error, e: print e else: # 关闭游标 cur.close() # 提交操作 conn.commit() # 关闭连接 conn.close() print u"创建数据库及表成功" def insertDatas(self): try: # 连接mysql数据库中具体某个库 conn = MySQLdb.connect( host = self.host, port = self.port, db = self.db, user = self.user, passwd = self.passwd, charset = self.charset ) cur = conn.cursor() # 向测试表中插入测试数据 sql = "insert into testdata(bookname, author) values(%s, %s);" res = cur.executemany(sql, [('Selenium WebDriver实战宝典', '吴晓华'), ('HTTP权威指南', '古尔利'), ('探索式软件测试', '惠特克'), ('暗时间', '刘未鹏')]) except MySQLdb.Error, e: raise e else: conn.commit() print u"初始数据插入成功" # 确认插入数据成功 cur.execute("select * from testdata;") for i in cur.fetchall(): print i[1], i[2] cur.close() conn.close() if __name__ == '__main__': db = DataBaseInit( host="localhost", port=3306, dbName="gloryroad", username="root", password="123456", charset="utf8" ) db.create() db.insertDatas() print u"数据库初始化结束"
MysqlUtil.py文件用于从数据库中获取测试数据,具体内容如下:
#encoding=utf-8 import MySQLdb from DataBaseInit import DataBaseInit class MyMySQL(object): def __init__(self, host, port, dbName, username, password, charset): # 进行数据库初始化 dbInit = DataBaseInit(host, port, dbName, username, password, charset) dbInit.create() dbInit.insertDatas() self.conn = MySQLdb.connect( host = host, port = port, db = dbName, user = username, passwd = password, charset = charset ) self.cur = self.conn.cursor() def getDataFromDataBases(self): # 从testdata表中获取需要的测试数据 # bookname作为搜索关键词,author作为预期关键词 self.cur.execute("select bookname, author from testdata;") # 从查询区域取回所有查询结果 datasTuple = self.cur.fetchall() return datasTuple def closeDatabase(self): # 数据库后期清理工作 self.cur.close() self.conn.commit() self.conn.close() if __name__ == '__main__': db = MyMySQL( host="localhost", port=3306, dbName="gloryroad", username="root", password="123456", charset="utf8" ) print db.getDataFromDataBases()
DataDrivenByMySQL.py文件用于编写数据驱动测试脚本代码,具体内容如下:
# encoding=utf-8 from selenium import webdriver import unittest, time import logging, traceback import ddt from MysqlUtil import MyMySQL 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, %Y-%m-%d %H:%M:%S', # 日志文件存放的目录(目录必须存在)及日志文件名 filename = 'D:\\test\\DataDrivenTesting\\report.log', # 打开日志文件的方式 filemode = 'w' ) def getTestDatas(): db = MyMySQL( host="localhost", port=3306, dbName="gloryroad", username="root", password="123456", charset="utf8" ) # 从数据库测试表中获取测试数据 testData = db.getDataFromDataBases() # 关闭数据库连接 db.closeDatabase() return testData @ddt.ddt class TestDemo(unittest.TestCase): def setUp(self): self.driver = webdriver.Ie(executable_path = "D:\\IEDriverServer") @ddt.data(*getTestDatas()) def test_dataDrivenByDatabase(self, data): # 对获得的数据进行解包 testData, expectData = data url = "http://www.baidu.com" # 访问百度首页 self.driver.get(url) # 将浏览器窗口最大化 self.driver.maximize_window() print testData, expectData # 设置隐式等待时间为10秒 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, e: logging.error(u"查找的页面元素不存在,异常堆栈信息:"\ + str(traceback.format_exc())) except AssertionError, e: logging.info(u"搜索“%s”,期望“%s”,失败" %(testData, expectData)) except Exception, 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()