一、Python数据驱动工具ddt
1、 安装
ddt pip install ddt
DDT是 “Data-Driven Tests”的缩写
资料:http://ddt.readthedocs.io/en/latest/
2、 DDT的使用
(1) ddt.ddt:
装饰类,也就是继承自TestCase的类
(2) ddt.data:
装饰测试方法。参数是一系列的值。
(3) ddt.file_data:
装饰测试方法。参数是文件名。文件可以是json 或者 yaml类型。
注意,如果文件以”.yml”或者”.yaml”结尾,ddt会作为yaml类型处理,其他所有文件都会作为json文件处理。
如果文件中是列表,每个列表的值会作为测试用例参数,同时作为测试用例方法名后缀显示。如果文件中是字典,字典的key会作为测试用例方法的后缀显示,字典的值会作为测试用例参数。
(4) ddt.unpack:
传递的是复杂的数据结构时使用。比如使用元组或者列表,添加unpack之后,ddt会自动把元组或者列表对应到多个参数上。字典也可以这样处理。
(5) 测试用例方法名生成规则
使用ddt后,会产生一个新的测试用例方法名:之前的测试用例方法名_ordinal_data
之前的测试用例方法名:即定义的测试用例方法名。比如def test_large(),这里就是test_large
ordinal:整数,从1开始递加。
data:如果传递过来的数据存在__name__属性,则这里就是该数据的__name__值。如果未定义__name__属性,ddt会尽量将传递过来的数据转化为python标识符,作为data显示。比如(3,2)就转化为3_2。需要注意的是,如果数据是字典,则这里就是字典的key。
二、实例演示
1、@ddt.ddt&&@ddt.data main.py: from selenium import webdriver import unittest, time import logging, 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 = 'e:/report.log', # 打开日志文件的方式 filemode = 'w' ) @ddt.ddt class TestDemo(unittest.TestCase): def setUp(self): self.driver = webdriver.Ie(executable_path = "c:\\IEDriverServer") @ddt.data([u"神奇动物在哪里", u"叶茨"], [u"疯狂动物城", u"古德温"], [u"大话西游之月光宝盒", u"周星驰"]) @ddt.unpack #解包,将测试数据对应到testdata 和 expectdata def test_dataDrivenByObj(self, testdata, expectdata): url = "http://www.baidu.com" # 访问百度首页 self.driver.get(url) # 设置隐式等待时间为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()
2、@ddt.file_data test_data_list.json: [ "邓肯||蒂姆", "乔丹||迈克尔", "库里||斯蒂芬", "杜兰特||凯文", "詹姆斯||勒布朗" ] main.py: from selenium import webdriver import unittest, time import logging, traceback import ddt from ReportTemplate import htmlTemplate from selenium.common.exceptions import NoSuchElementException #如果有no json的报错信息,请将json文件存储为utf-8,with Bom # 初始化日志对象 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 = 'e:/report.log', # 打开日志文件的方式 filemode = 'w' ) @ddt.ddt class TestDemo(unittest.TestCase): @classmethod def setUpClass(cls): # 整个测试过程只被调用一次 TestDemo.trStr = "" def setUp(self): self.driver = webdriver.Ie(executable_path = "c:\\IEDriverServer") status = None # 用于存放测试结果状态,失败'fail',成功'pass' flag = 0 # 数据驱动测试结果的标志,失败置0,成功置1 @ddt.file_data("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, expectdata = tuple(value.strip().split("||")) # 设置隐式等待时间为10秒 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(expectdata in self.driver.page_source) except NoSuchElementException, e: logging.error(u"查找的页面元素不存在,异常堆栈信息:" \ + str(traceback.format_exc())) status = 'fail' flag = 0 except AssertionError, e: logging.info(u"搜索“%s”,期望“%s”,失败" %(testdata, expectdata)) status = 'fail' flag = 0 except Exception, e: logging.error(u"未知错误,错误信息:" + str(traceback.format_exc())) status = 'fail' flag = 0 else: logging.info(u"搜索“%s”,期望“%s”通过" %(testdata, expectdata)) status = 'pass' flag = 1 # 计算耗时,从将测试数据输入到输入框中到断言期望结果之间所耗时 wasteTime = time.time() - start - 3 # 减去强制等待的3秒 # 每一组数据测试结束后,都将其测试结果信息插入表格行 # 的HTML代码中,并将这些行HTML代码拼接到变量trStr变量中, # 等所有测试数据都被测试结束后,传入htmlTemplate()函数中 # 生成完整测试报告的HTML代码 TestDemo.trStr += u''' <tr> <td>%s</td> <td>%s</td> <td>%s</td> <td>%.2f</td> <td style="color:%s">%s</td> </tr><br />''' % (testdata, expectdata,startTime, wasteTime, flagDict[flag], status) def tearDown(self): self.driver.quit() @classmethod def tearDownClass(cls): # 写自定义的html测试报告 # 整个测试过程只被调用一次 htmlTemplate(TestDemo.trStr) if __name__ == '__main__': unittest.main()