25.自动化测试架构优化

发布时间 2023-12-23 10:22:35作者: 想要暴富的小男孩

打造测试框架的需求与价值

  • 领域模型适配:封装业务实现,实现业务管理
  • 提高效率:降低用例维护成本,提高执行效率
  • 增强功能:解决已有框架不满足的情况

自动化框架应具备的功能

  • 支持管理用例,运行用例
  • 支持查找元素/定位元素,对元素/页面 进行各种操作(点击,滑动,输入等等)
  • 支持生成测试报告
  • 能够实现功能的复用,(比如登录,搜索等)
  • 当页面有异常弹框的时候,可以进行有效的处理
  • 当用例失败,需要添加失败时的日志,截图,等信息,放在测试报告中
  • 多设备并发
  • 支持平台化

自动化测试框架实现

 
功能实现
管理用例,运行用例 pytest
查找元素/定位元素 Appium
测试报告 Allure
功能复用 PO 实现
异常弹框 编写代码
失败时的日志,截图 编写代码
多设备并发 selenium grid
平台化 VUE+FLASK/Django
   

项目结构

为什么要封装框架?

  • 复用
  • 平台化

增强功能

  • 需求与价值
  • 项目结构优化
  • 框架封装

需求与价值

项目结构优化

  • 框架层
  • 业务层
  • 用例层

框架封装

  • 异常处理(弹窗黑名单)
  • 日志记录
  • 报告生成
  • 数据驱动

异常处理(弹窗黑名单)

# 声明一个黑名单
def black_wrapper(fun):
def run(*args, **kwargs):
basepage = args[0]
try:
return fun(*args, **kwargs)
except Exception as e:
for black in black_list:
eles = basepage.driver.find_elements(*black)
if len(eles) > 0:
eles[0].click()
return fun(*args, **kwargs)
raise e

return run

@black_wrapper
def find(self, by, locator)
return self.driver.find_element(by, locator)

日志记录

  • 运行日志记录
  • 错误日志记录
import logging
logging.basicConfig(level=logging.INFO)

def black_wrapper(fun):
def run(*args, **kwargs):
basepage = args[0]
try:
logging.info("start find: \nargs: " + str(args) + " kwargs: " + str(kwargs))
return fun(*args, **kwargs)
except Exception as e:
basepage.screenshot("tmp.png")
with open("./tmp.png", 'rb') as f:
picture_data = f.read()
allure.attach(picture_data, attachment_type=allure.attachment_type.PNG)
for black in basepage.black_list:
eles = basepage.driver.find_elements(*black)
if len(eles) > 0:
eles[0].click()
return fun(*args, **kwargs)
raise e

return run

报告生成

  • 异常日志
  • 异常截图
  • 测试用例步骤
  • 测试描述
  • bug,issue 关联
  • 用例分类(feature,story,step 等)

参数化与数据驱动

  • 支持支持测试用例 / 步骤层级的参数化驱动配置
  • 配置方式包括三个部分
  • 参数定义(指定名字)
  • 数据源指定(指定 yaml 文件 /或者其它格式文件)
  • 数据源准备(无论是从线上环境 捞的数据,还是自己创建的测试数据)

总结

  • 自动化测试框架应具备的功能
  • 自动化测试框架优化(在 PO 的基础上,添加异常处理,日志,报告 ,截图,参数化与数据驱动等)逐步的将框架完善
pip install allure-pytest
pytest test_xxx.py --alluredir=./result
allure serve ./result

数据驱动

- find: //*[@text='xxxx']
  action: find_and_click
- find: //*[@text='xxxx']
  action: send
  content: 123
def load(self, yaml_path):
    with open(yaml_path, encoding="utf-8") as f:
        data = yaml.load(f)
    for step in data:
        xpath_expr = step.get("find")
        action = step.get("action")
        if action == "find_and_click":
            self.find_and_click(By.XPATH, xpath_expr)
        elif action == "send":
            content = step.get("content")
            self.send(By.XPATH, xpath_expr, content)