- 为何我们要拥有一个属于自身的接口自动化测试框架呢, 这便是项目概述所涉及的内容。
经历了这么多年的测试工作, 从最初的手工点点点操作, 到变为脚本方式, 再发展到自动化阶段, 我体悟最深的是, 一个称手的自动化测试框架, 好似战士手中的枪, 如同程序员手中的IDE, 能够使你从重复性劳动里释放出来, 进而将精力切实投入到更具价值之处, 比如构思更为刁钻的测试场景, 或者深度剖析业务逻辑。今天所要谈及的"接口自动化测试框架搭建", 便是这般一个核心的生产力工具。它并非是一个现成可用的工具, 而是一套由你亲自搭建的、契合你项目需求的、具备可维护性、拥有可扩展性的代码工程体系。
详细来讲, 它究竟可以帮你达成什么样的事情? 设想一下这种情形, 你所负责的乃是一个采用微服务架构的产品, 存在着几十乃至上百个接口, 而后在每一次进行迭代操作的时候, 都需要开展回归测试。要是采用手动调用的方式, 那么效率极为低下并且还特别容易出现差错。倘若使用现成的工具, 其灵活性欠佳, 二次开发所需要的成本却很高, 生成的报告也说不定没办法契合团队的要求。然而有一个自行构建的框架, 其核心目的便是要达成于接口测试方面存在的自动化执行, 以及结果校验, 还有报告生成以及持续集成等等。它适合哪类人? 无论是才开始接触自动化, 想要按照系统的方式去学习的测试新人, 还是因为现有的工具没办法满足自身需求, 而想着自己动手打造工具的资深测试开发人员, 这一套自始至终的搭建思路都能够给你直接性的参考。
市面上存在着诸多优秀的开源框架, 像 + 这类, 又或者是 + 这类。然而直接将其拿来使用, 与自己从一开始进行完整搭建, 二者在理解深度方面是全然不一样的。自己去搭建框架, 你会被强制去思索:测试数据要怎样进行管理? 用例以何种方式组织才能变得清晰? 断言该如何撰写才足够健壮? 报告要怎样定制才能够显得好看? 怎样来实现与集成? 这些问题的答案, 便构建成了一个框架的灵魂所在。接下来, 我会依据最近一次针对金融项目搭建框架的实战经历, 把每个环节当中的"为什么"以及"怎么做"详细透彻地说明白。
- 关于框架的整个设计以及核心思路的拆解, 具体到2.1所示的框架选型背后具体存在着何等样式的逻辑, 也就是表述此为何便是那个加上的问号所对应的情况呢?
所选技术栈当属起始首要步骤, 此对后续开发之效率以及框架生态与否的情况产生决定作用。我将某两者选定为核心, 是依循以下几个极为实在的考虑因素而言的:
首先, 其语法具备简洁这一特性, 上手速度较快。测试团队当中的同学, 他们的编程基础状况或许存在差异, 相较于Java、Go等语言而言, 它更为友好, 能够促使团队更迅速地投身于用例编写以及维护工作当中。其次, 它的生态极为丰富。某库处理HTTP请求属于行业标准 , 某框架是功能强大并且插件丰富的测试执行框架 , 它能够生成极为美观的测试报告 , 还有其他工具方便处理各种格式的测试数据。这些成熟的工具能让我们将精力集中于业务逻辑封装方面, 而非去重复制造基础组件。
为啥不选用现成的平台化工具呢, 比如说或者的自动化功能, 对于中小型且接口相对稳定的项目而言, 它们确实高效, 然而对于接口数量庞大、业务逻辑复杂还需要深度定制(像是加解密、动态签名、数据库校验)的项目来讲, 代码化的框架灵活性是无可替代的, 你能够精确控制测试的每一个环节, 方便地集成到CI/CD流水线, 而且所有测试资产(代码、数据)都能用Git进行版本管理, 协作和回溯相当清晰。
2.2 框架的顶层架构设计
一个体魄强健的框架, 其结构具备条理清晰的特征相较于代码呈现出华丽的特质而言显得更为关键。我所运用的是一种层次分明的架构方式, 其核心的理念为"将关注点予以分离", 使各个不同的模块能够依据自身职责发挥相应作用。整体的结构情况如下:
project/
├── common/ # 公共层
│ ├── __init__.py
│ ├── logger.py # 日志模块
│ ├── config.py # 配置文件读取
│ └── request_client.py # 封装的HTTP请求客户端
├── test_data/ # 数据层
│ ├── __init__.py
│ ├── api_data.yaml # 接口基础数据(URL,方法)
│ └── case_data/ # 用例数据,可按模块分文件
├── test_cases/ # 用例层
│ ├── __init__.py
│ ├── conftest.py # pytest共享夹具
│ └── test_user.py # 具体的测试模块
├── utils/ # 工具层
│ ├── __init__.py
│ ├── assert_utils.py # 自定义断言
│ ├── db_utils.py # 数据库操作
│ └── encrypt_utils.py # 加解密工具
├── reports/ # 报告目录(自动生成)
├── logs/ # 日志目录(自动生成)
└── run.py # 主执行入口
为什么这么分?
- 关于核心模块之中,细节实现的相关情况, 以及避坑指南, 其中包含, 3.1部分所涉及的, HTTP请求客户端的深度封装。
这是用于构建框架与外界进行交互的一座桥梁, 其封装所拥有的健壮程度, 直接对用例具备的稳定性以及编写能够达到的效率有着决定性作用。直接以裸用的方式去处理, 尽管会显得较为灵活, 然而却会生成大量存在重复情况并且容易出现错误的代码。
基础封装示例:
python
# common/request_client.py
import requests
from common.logger import get_logger
class RequestClient:
def __init__(self, base_url=None):
self.session = requests.Session() # 使用Session保持会话(如cookie)
self.base_url = base_url
self.logger = get_logger(__name__)
# 可以在这里加载全局配置,如默认请求头
self.default_headers = {
"Content-Type": "application/json; charset=UTF-8",
"User-Agent": "AutoTestFramewo