关键字 + yaml数据 驱动设计— Selenium二次封装与集成(Unittest+ddt+PyYMAL)
四、数据驱动 + 关键字驱动 Selenium二次封装与集成(Unittest+ddt+PyYMAL)
1.关键字驱动主要应用方向和优点:
对于多系统的复用性,一套代码可支持多系统,POM只能支持单一系统
简化代码降低冗余,提升复用性、可维护性
2.关键字驱动体系下的结构:
1.逻辑代码 web_key_demo.py
2.测试代码 case_demo03.py
3.测试数据 search.yaml
基于 数据驱动 + 关键字驱动 实现的自动化测试效果。
4.1 关键字驱动类(逻辑层)
对于线性代码进行封装,这样我们就得到封装后的方法
# web_key_demo.py +++++++++++++++++++++++++++++ """ 关键字驱动类:底层逻辑代码,这个类不会直接执行测试行为。 属于逻辑层代码,常规的操作行为封装成自定义的关键字函数。 在执行自动化的时候,通过调用自定义函数类,来实现自动化测试操作。 常规操作行为: 1.创建浏览器对象 2.访问url 3.元素定位 4.输入 5.点击 6.其他... """ from selenium import webdriver #基于type生成对应的浏览器对象 def browser(type_): try: # driver本身只限于webdriver对象 driver = getattr(webdriver,type_)() except Exception as e: driver = webdriver.Chrome() return driver class KeyDemo: def __init__(self, type_): self.driver = browser(type_) #访问url def open(self,url): self.driver.get(url) #元素定位:8种元素定位 def locator(self,name,value): return self.driver.find_element(name,value) #输入 def input(self, name,value,txt): self.locator(name, value).send_keys(txt) #点击 def click(self, name,value): self.locator(name,value).click() #关闭浏览器 def quit(self): self.driver.quit() # 睡眠 def sleep(self,time_): time.sleep(time_)
4.2 测试用例(unittest初探)
基于封装后的方法线性代码可以这样写:
# case_demo.py ++++++++++++++++++++++++++ from web_key_demo import KeyDemo kd = KeyDemo('Chrome') kd.open( ' http://www.baidu.com ' ) kd.input( 'id', 'kw','美女') kd.click( 'id' , 'su') kd.sleep(3) kd.quit()
对于多个测试用例可以引入unittest管理:
# case_demo02.py ++++++++++++++++++++ import unittest from web_key_demo import KeyDemo class CaseDemo(unittest.TestCase): def test_01(self): # 测试用例名字需要以test开头 kd = KeyDemo('Chrome') kd.open(' http://www.baidu.com ') kd.input('id', 'kw', '美女') kd.click('id', 'su') kd.sleep(3) kd.quit() def test_02(self): kd = KeyDemo('Chrome') kd.open(' http://www.baidu.com ') kd.input('id', 'kw', '妹子') kd.click('id', 'su') kd.sleep(3) kd.quit() if __name__ == '__main__': unittest.main() # 只要运行这个,就会逐个运行CaseDemo下test开头的方法,如test_01和test_02
4.3 数据层(unittest + ddt + yaml)
上面代码可以发现测试用例01和02只是数据不同,可以采取数据驱动
unittest 和 ddt 有很好的契合度,ddt读取的数据可以直接用于unittest
首先需要安装ddt和PyYAML模块,用ddt读取yaml数据文件中一组一组数据为一个个的字典,逐个传入测试用例来执行
# case_demo03.py ++++++++++++++++++++ import unittest from ddt import ddt,file_data from web_key_demo import KeyDemo @ddt # 装饰ddt来管理测试类 class CaseDemo(unittest.TestCase): @file_data('./data/search.yaml') # ddt模块读取文件中数据转化为一组一组数据传入测试用例 def test_01(self, url, _input, click): # 测试用例名字需要以test开头 kd = KeyDemo('Chrome') kd.open(url) kd.input(**_input) kd.click(**click) kd.sleep(3) kd.quit() if __name__ == '__main__': unittest.main()
代码还可以简化为:
import unittest from ddt import ddt,file_data from web_key_demo import KeyDemo @ddt # 装饰ddt来管理测试类 class CaseDemo(unittest.TestCase): # 在测试用例执行前先执行 def setUp(self) -> None: self.kd = KeyDemo('Chrome') # 测试用例执行后紧接着执行 def tearDown(self) -> None: self.kd.quit() @file_data('./data/search.yaml') # ddt模块读取文件中数据转化为一组一组数据传入测试用例 def test_01(self, url, _input, click): # 测试用例名字需要以test开头 self.kd.open(url) self.kd.input(**_input) self.kd.click(**click) self.kd.sleep(3) if __name__ == '__main__': unittest.main()
- # 一个符号表示一组数据,ddt读取后是一个字典 url : http://www.baidu.com _input: name: id # _input下的一组数据,读取后字典键值对的value是一个字典 value: kw txt: 美女 click: name: id value: su - url : http://www.baidu.com _input: name: id value: kw txt: 妹子 click: name: id value: su - url : http://www.jd.com _input: name: id value: key txt: 不可描述的好东西 click: name: xpath value: //button[@aria-label='搜索']
注意执行的时候光标不能放入CaseDemo类中,需要放到外面,点一下其他位置再执行,不然会报错
AttributeError: type object 'CaseDemo' has no attribute 'test_01'
Error Traceback (most recent call last): File "E:\python3.8\lib\unittest\case.py", line 60, in testPartExecutor yield File "E:\python3.8\lib\unittest\case.py", line 676, in run self._callTestMethod(testMethod) File "E:\python3.8\lib\unittest\case.py", line 633, in _callTestMethod method() File "E:\python3.8\lib\unittest\loader.py", line 34, in testFailure raise self._exception File "E:\python3.8\lib\unittest\loader.py", line 169, in loadTestsFromName parent, obj = obj, getattr(obj, part) AttributeError: type object 'CaseDemo' has no attribute 'test_01'