ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[TOC] ``` 一、数据驱动 1.1 什么是数据驱动? 说明: 1. 通过测试数据控制用例的执行,直接影响测试结果; 2. 数据驱动是最好结合PO+参数化技术使用; 1.2 数据驱动优点 将维护关注点放到测试数上,而不去关注测试脚本代码; 1.3 数据驱动常用的格式 1.json(重点) 2.xml 3.excel 4.csv 5.txt 1.4 json介绍 1. 一种纯文本格式,后缀.json; 2. 一种轻量级数据交换格式:(接口数据传递基本使用 json格式) 3. 由键值对组成,和 python的字典格式一模一样,不同之处在于(json是文本格式) 4. json语法:花括号包含键值对,键与值之间使用冒号(:)分隔,键值对之间使用逗号(,)分隔; 1.5 json与字典转换 1).字典转为json字符串 方法: dumps() 操作: 1.导包 2.调用dumps方法 3.打印类型 注意: 使用dumps方法,而不是dump方法; 2)json字符串转字典 方法:1oads() 操作: 1.导包 2.调用1oads方法 3.打印类型 注意: 1.使用1oads方法而不是1oad方法; 2.字符串中的键名必须使用双引号; ``` <details> <summary>test01_dict_json.py</summary> ``` # test01_dict_json.py ''' 目标:将python中的字典转换为 json字符串 案例: data = {"name":"张三", "age":18} 操作: 1. 导包 import json 2. 调用dumps()方法 将字典转换为 json字符串 注意: json中:还有一个方法 dump()写入json,勿要选错; ''' import json '''将字典转换为json字符串''' # data = {"name":"张三", "age":18} # # 调用dumps进行转换json字符串 # print("转换之前的数据类型:", type(data)) # d2 = json.dumps(data) # print("转换之后的数据类型:", type(d2)) ''' 目标:将字符串转为json 方法:loads()将字符串转为字典 注意:load() 此方法为读取json方法,千万别写错了。 ''' data = "{'data':'张三', 'age':18}" # 注意错误写法,属性名必须使用双引号 data = '{"data":"张三", "age":18}' print("转之前:", type(data)) d3 = json.loads(data) print("转之后:", type(d3)) ``` </details> <br /> <details> <summary>test02_json_write.py</summary> ``` # test02_json_write.py ''' 目标:写入json 案例: 1. data = {"name":"tom", "age":18} 2. data = {"name":"李四", "age":18} 操作: 1. 导包json 2. 方法 dump 注意: 1. 写入操作 w 2. 写入方法:dump()而不是dumps() ''' import json # data = {"name":"tom", "age":18} data = {"name":"李四", "age":18} # 获取文件流 并 写入数据 with open("../data/write.json", "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False) ``` </details> <br /> <details> <summary>test03_json_read.py</summary> ``` # test03_json_read.py ''' 目标:读取json 案例: 读取 data/write.json 操作: 1. 导包 json 2. 方法 load(文件流) 注意: 1. 读取操作 r 2. 读取方法:load()而不是loads() ''' import json # 打开要读取的文件流 并调用 load方法 with open("../data/write.json", "r", encoding="utf-8") as f: data = json.load(f) print(data) ``` </details> <br /> ``` drvier封装 类名 # 定义类变量 driver = None @classmethod # 获取 driver方法 如果 cls.driver is None: # 获取浏览器驱动对象 # 最大化 # 打开url 注:url建议写入配置文件中 返回 c1s.driver @classmethod # 关闭driver方法 如果c1s.driver: cls.driver.quit() # 注意此处一定要置空 cls.driver = None ``` ![6FCDF61E-5689-413A-B21E-3D1480D0FFD9.jpg](https://i.loli.net/2021/01/20/CP9qI4OviejY2k1.jpg) <details> <summary>base/base.py</summary> ``` # base/base.py from selenium.webdriver.support.wait import WebDriverWait import time class Base: def __init__(self, driver): self.driver = driver def base_find_element(self, loc, timeout=30, poll=0.5): ''' :param loc: 元素的定位信息,格式为元组 :param timeout: 默认超时时间30秒 :param poll: 访问频率,默认0.5秒查找一次元素 :return: 返回查找到的元素 ''' # 显示等待 return WebDriverWait(self.driver, timeout=timeout, poll_frequency=poll).\ until(lambda x:x.find_element(*loc)) def base_click(self, loc): self.base_find_element(loc).click() # 获取value属性方法封装 def base_get_value(self, loc): # 使用get_attribute()方法获取指定的元素属性值 # 注意:返回 return self.base_find_element(loc).get_attribute("value") # 截图 def base_get_img(self): self.driver.get_attribute_as_file( "../image{}.png".format(time.strftime("%Y_%m_%d %H_%M_%S"))) ``` </details> <br /> <details> <summary>base/get_driver.py</summary> ``` # base/get_driver.py from selenium import webdriver from day07.po1 import page class GetDriver: # 设置类属性 driver = None @classmethod def get_driver(cls): if cls.driver is None: cls.driver = webdriver.Chrome() cls.driver.maximize_window() cls.driver.get(page.url) return cls.driver # 退出driver @classmethod def quit_driver(cls): if cls.driver: cls.driver.quit() # 注意:此处有一个大坑 cls.driver = None if __name__ == '__main__': # 第一次获取浏览器 print(GetDriver().get_driver()) # 第二次获取浏览器 print(GetDriver().get_driver()) # 调用关闭,测试 关闭后driver是否为None GetDriver().quit_driver() # print(GetDriver().get_driver()) ``` </details> <br /> <details> <summary>page/__init__.py</summary> ``` # page/__init__.py from selenium.webdriver.common.by import By '''以下为服务器域名配置地址''' url = "http://cal.apple886.com/t" '''以下为计算器配置数据''' # 由于数字键有一定的规律,所以暂时先不用定位此键,用到的时候再考虑 clac_num = By.CSS_SELECTOR, "simple9" # 加号 clas_add = By.CSS_SELECTOR, "#simpleAdd" # 等号 clac_eq = By.CSS_SELECTOR, "#simpleEqule" # 获取结果 clac_result = By.CSS_SELECTOR, "resultIp" # 清屏 clac_clear = By.CSS_SELECTOR, "#simpleClearAllBtn" ``` </details> <br /> <details> <summary>page/page_calc.py</summary> ``` # page/page_calc.py from selenium.webdriver.common.by import By from day07.po1.base import Base from day07.po1 import page class PageCalc(Base): # 点击数字方法 def page_click_num(self, num): # 拆开单个按钮的定位方式 for n in str(num): loc = By.CSS_SELECTOR, "simple{}".format(n) self.base_click() # 点击加号 def page_click_add(self): self.base_click(page.clac_add) # 点击等号 def page_click_eq(self): self.base_click(page.clac_eq) # 获取结果方法 def page_get_value(self): return self.base_get_value(page.clac_result) # 点击清屏 def page_click_clear(self): self.base_click(page.clac_clear) # 截图 def page_get_image(self): self.base_get_img() # 组装加法业务 def page_add_calc(self, a, b): self.page_click_num(a) self.page_click_add() self.page_click_num(b) self.page_click_eq() ``` </details> <br /> <details> <summary>scripts/test_calc.py</summary> ``` # scripts/test_calc.py import unittest from parameterized import parameterized from day07.po1.page.page_calc import PageCalc class TestCalc(unittest.TestCase): @classmethod def setUpClass(cls): cls.calc = PageCalc() def tearDown(cls) -> None: pass @parameterized.expand([1, 2, 3]) def test_add_calc(self, a, b, expect): self.calc.page_add_calc(a, b) try: self.assertEqual(self.calc.page_get_value(), expect) except: self.calc.page_get_image() ``` </details> <br />