自动化测试平台(以下简称平台)由前端人机交互界面(以下简称UI界面)和后端自动化测试框架(以下简称框架)组成。
本项目是基于 徐德晨等前辈 撰写的**《高效自动化测试平台——设计与开发实战》一书的读书笔记**。
同时,在代码上写了自己阅读时的笔记。
语言:python
1.测试用例的复用、扩展能力:测试用例可以复用在同类产品的不同型号;根据测试对象,决定测试点的通过条件;底层组件进行封装说明生成详细的API文档。
2.测试工具的扩展能力:将设备或工具提供的接口封装成符合我们自己规范的接口或者模块;能够快速添加支持;相同操作逻辑的测试用例尽可能少的更改。
3.灵活配置和测试调度能力:可以按照使用者的意愿决定测试用例的执行数量与执行次数。
4.测试结果和报告:测试报告能够以树形或表格等数据结构清晰展示出来;能够进行横向或纵向比较;可以对测试结果提供补充说明
5.与CI/CD集成的能力:提供一定的方法集成到CI/CD的工具中,通过工具来测试,并将测试结果返回给CI/CD的工具中。【持续集成】
6.快速部署与较低的学习成本:不需要过多的额外配置,通过容器部署与销毁;完善的开发文档与使用文档;工具本身的易用性和使用逻辑的设计合理;用户可视化界面
7.跨平台兼容性考虑:定义跨编程语言模块之间的通信接口,如提供命令行调用的方式、远程RPC调用。
- 测试框架能否满足团队日常的测试需求
- 框架是否具有扩展性
- 是否可以快速定位框架内部存在的问题
- 与团队其他工具的兼容性
平台设计要保证核心功能和业务分离,即对核心业务进行总结和抽象。当在开发过程中发现一个功能可以被大量地复用时,就要考虑这些功能是否能够被抽象出来,并添加到核心功能中。本框架采用如下设计模型。
表示层: 测试用例
中间层: 测试平台(引用底层提供的功能,对特定的业务逻辑进行封装,将测试逻辑提供测试用例调用)
数据层: 具体的技术代码(比如和测试设备之间的通信协议、UI测试中对UI元素的封装、测试结果的存储、测试资源的序列化)。
- 用户定义的资源类型和配置,对测试引擎来讲不可见
- 资源和配置的实例化,需要使用动态引用或抽象类的方法让用户自己定义实例化的过程
- 好处:平台核心模块适用性强,满足不同的团队需要
- 缺点:开发复杂
- 仅要求测试引擎不引用测试用例,而引用用户定义的资源和配置
- 平台开发人员:包含测试引擎、测试报告结果、资源模块、测试配置模块
- 测试用例开发人员:测试用例、测试资源模块、配置模块
- 优点:开发简单
- 缺点:都对测试资源模块和测试配置模块进行维护,不同人维护同一份代码,容易冲突
- 确定模块的功能边界,并且对功能的调用接口进行了严格的定义和封装 ,模块内部的逻辑不在直接暴露给外部。
- 模块之间进行解耦合。例如:将查询的行为进行封装,让参数变得和具体SQL语言无关。
- 功能设计时,将具体的业务进行分类,使得模块的调用关系呈现单向性、禁止相互依赖。
- 设计先行,保障扩展性和维护性。
- 测试资源描述方法的定义
- 测试资源的保存和读取
- 测试资源的选择
- 配置的保存和堆区
- 配置的自动生成和默认值
- 动态配置的能力
- 带逻辑功能的配置
- 测试资源、配置、和测试报告的初始化
- 测试用例配置注入
- 测试用例列表的执行逻辑
- 动态方式扫描获取测试用例
- 静态方式扫描
- 测试步骤格式化输出
- 测试执行过程的日志
- 日志注册机制
- 日志分类
- 基于命令行实现
- 基于RESTful实现
- 基于GUI实现
测试资源主要包括2部分:测试资源 + 资源间的逻辑操作关系。测试资源本质上是为了提供测试环境的配置信息。将测试资源封装成特定的测试资源池,以便进行统一调用与管理。
测试资源库功能包括:资源的创建与删除,资源间的冲突检测,资源文件的加载与保存(序列化与反序列化),利用资源选择器进行资源约束。
**第一,定义测试资源。应分析测试过程中所遇到的测试资源的种类,并通过面向对象的方法(封装、继承、抽象、多态)**表示测试资源,以便测试资源发生变动时进行快速修改。(如:类 DevicePort)
第二,定义资源间的逻辑操作关系。基于依赖关系实现测试资源之间的逻辑操作,并开放接口给资源池。(如:类 ResourceDevice)
第三,解耦资源实例化与资源管理模块。 基本思想是资源管理模块不负责具体的的实例化,而让调用者根据获取的资源设备自己进行实例化。测试资源只负责测试环境静态信息的维护,但是我们可以通过回调的方法 将实例化接口提供给其他模块。
本框架:
1. 添加**2个字典数据结构**,保存资源类型和实例化方法的映射关系;
2. 添加**注册资源**接口实例化的方法或类(如:register_resource());
3. 通过回调函数交由业务层自行注册所需的测试资源具体的实例,核心层利用全局变_resource_XXX_mapping存储具体的实例化句柄。
4. 业务层**从资源池中收集资源** 再通过调用 get_comm_instance()获取具体的实例化句柄。
第四,实现测试资源池。 首先,需要有快速序列化和反序列化测试资源的能力;其次,需要对测试资源进行冲突检测与避免的机制,如采用锁机制(👀框架内尚未完善)。最后,进行测试资源限制器和测试资源的双选。两种选择方式:
-
根据测试资源选择相应的资源限制器;
-
根据资源限制器选择相应的测试资源。
- 优点:简单、直接,没有任何技术复杂性
- 缺点:效率低、不适合封装成测试数据工具、成功率低、引入不必要依赖
- 优点:保证准确性、执行效率高、封装简单、同步更新
- 缺点:不支持数据库CRUD操作、API之间的依赖关系、海量数据创建困难
- 优点:数据生成效率高
- 缺点:维护成本高、数据完整性差、SQL语句变化需要及时维护
- 方法:API调用生成基础的测试数据,然后使用CRUD操作生成符合特殊测试需求的数据
- 创建数据耗时较长
- 数据被修改无法正常使用
- 微服务架构测试环境不稳定
- 实时创建(On-the-fly)
- 耗时长
- 测试数据关联性强
- 微服务架构调整(服务并非100%可用)
- 预先创建(Out-of-box)
- 存在 ”脏数据“(在被使用前发生了非预期的修改)(优化流程控制解决)
- 不适用一次性使用的测试数据场景
- 综合运用
- 死水数据:相对稳定,不会再使用过程中改变状态,且可被多次使用的数据**(预先创建)**
- 活水数据:经常修改,一次性使用的数据。(实时创建)
UserBuilder.with_country("UK").with_payment('Paypal').build()# 搜索符合条件的测试数据,找到返回,否则失败
UserBuilder.with_country("UK").with_build_strategy('BuildStrategy.SEACH_ONLY').build()
# 创建符合要求的数据
UserBuilder.with_country("UK").with_build_strategy('BuildStrategy.CREATE_ONLY').build()
# 先搜索如果有就返回, 没有就创建
UserBuilder.with_country("UK").with_build_strategy('BuildStrategy.SMART').build()
# 返回OUT_OF_BOX中符合要求的数据, 没有就返回失败
UserBuilder.with_country("UK").with_build_strategy('BuildStrategy.OUT_OF_BOX').build()- 引入内部数据库: 存放创建的测试数据的元数据
- 引入Core Service: 提供高质量和数量的管理机制
- Core Service –> 后台创建Jekins Job -> 创建成功ID保存数据库
- 适用: 频繁变化的值、量大的值
- 将需要循环或遍历的测试参数数据化
- 如果明确运行过程或参数,将数据保留在测试用例内
- 不适用数据描述复杂操作
- 完全固定的测试数据: 在测试用例内硬编码
- 相对不稳定的数据:作为数据文件,通过数据驱动方式的方式提供
- 灵活且大量的数据:测试数据平台方式,结合数据驱动的字符串和关键字函数的方法提供
- 出现重复的封装作业
- 封装代码具有极高的重复性
- 一些操作过程本身可以被重用,重用部分可以通过某种方式去自动生成
- 通过文档或元数据来简化测试代码的生成
- 元数据(规则或定义来描述协议报文或API):通过特定的规则来描述数据的结构和属性(与编程语言无关且无二义性)
- RESTful API 的 OpenAPI 标准
- Schema定义
简单,但生成代码格式糟糕
- 适用预设计的模板并替换其中的关键词,以生成代码
- 如果代码的逻辑本身不确定,
(代码实现见src\third_part\casegen)
- 利用文档对象来描述整个代码的结构。将代码中的元素对象化,并构造整个代码的模型,通过模型对象来生成相应的代码
- 可读性较强,又可以避免模板法产生的限制。
- 分析标准的定义模式
- 手动写出封装代码的实现
- 根据标准的定义设计标准所对应的中间对象
- 通过中间对象生成相应的封装代码
-
传统的自动化测试用例存在:覆盖度不够、组合不灵活、很难用现有测试用例复现客户的问题
-
自动化测试用例无法很好地覆盖复杂环境测试、客户现场地测试
- 拆分原来测试用例中的步骤,使用事件的方式提供给测试执行者自由设计测试用例
- 与关键字驱动的区别:事件驱动中每个事件,以类或模块为单位,在独立进程和线程中运行。其事件可以在测试执行过程中进行动态修改
APScheduler完成
- 合理地设计颗粒度来初步解决事件之间地依赖问题
- 数据暂存器来共享事件之间地数据
- 锁机制来解决竞争问题(事件级别锁 or 资源级别锁)
- 执行时作为普通测试用例驱动,并通过polling方法读取JSON、XML等数据文件或数据库,动态地在执行期间加载事件
- 调度器:从事件描述数据中获取事件的名称和参数信息 –> 从事件仓库中查找相应的类 –> 实例化输出到执行计划队列
- 计划任务池:定时器机制
- 锁服务
- 数据暂存器
包含:名称、参数、类型、执行相关参数、锁、结果、预处理、执行、清理
通过复用中间层完成封装
- 用来发起测试执行的路口
- 提供GUI界面和RESTful API,对外提供服务
- 兼具 版本控制、jenkins测试、job管理、测试执行结果
- 通过Sprint Boot框架提供RESTful API
- 内部实现调度Jenkins Job发起测试
- 引入内部数据库,实现测试版本管理和测试执行结果管理
-
用户不需要知道内部执行的细节
-
来测试环境中创建(搜索)符合要求的测试数据
-
必须设计成一个开放平台,任何开发人员通过脚手架代码贡献新的数据支持
功能:主要用于安装部署被测系统和软件
原理:脚本文件、命令行安装、引导式安装、silent安装
调用:持续集成成CI的流水线脚本来调用
用于微服务场景,用于提供能够正常开展测试的Mock
类似App Store, 各种有效小工具的集合










