共计 6436 个字符,预计需要花费 17 分钟才能阅读完成。
“如何保证质量”一直是产品或项目过程中关注的焦点,而测试是产品质量把控环节中非常关键的部分。本文结合我们的实践经验,总结出一套有效的自动化测试组合拳。
一、背景
我们的测试工作经历了以下四个阶段。
第一阶段,产品需求评审完成,开发团队实现功能开发,然后草草提测,不写单元测试。测试人员进行人工测试,没有工具或系统做辅助,测试用例编写是在 excel 或脑图中呈现。这个阶段只对业务熟悉,开发只关注功能实现。
第二阶段,产品需求评审完成,开发团队实现功能开发,写自身功能相关的单元测试,组长 review 组内代码。测试方面,依然处于人工检测功能测试阶段,但开始有一些相关的小工具辅助测试。在两轮或多轮测试情况下,回归一直是一个问题,还有分支测试完成,主干回归的过程,测试环境、预发布环境、灰度环境、线上环境等测试回归效率很低,人工测试在这方面的不足格外明显。
第三阶段,随着业务的发展产品功能需要快速上线,同时系统技术不断迭代,质量也面临着从未有过的挑战,人肉战术不是长久之计。在此阶段部门做了很多改进,引入和开发了很多测试辅助工具,如项目管理工具、测试用例管理工具、BUG 管理工具、自动发布系统、自动打包等。
- 搭建测试用例管理工具,方便编写及后期跟踪用例。一轮二轮测试人员如何分配;用例状态的管理是通过、挂起还是失败,一目了然。
- BUG 管理工具,主要是给开发和测试人员使用,通过文字和图片结合的方式描述功能问题,减少了开发和测试的沟通成本。
- 项目方面也开发出项目管理工具,方便查看项目状态和人力资源情况,在项目中做到很好的呈现。
- 在此阶段我们开始研发 UI 自动化测试工具,直观的想法是减少人工测试成本,提高测试效率。
- 自动化部署系统让开发环境、测试环境、灰度环境和线上环境做到很好的隔离,每个阶段更清晰,避免相互干扰引起的问题。
- APP 方面结合 Jenkins 可以实现自动打包,测试起来做到了开发和测试都以版本控制系统为主。
第四阶段,因为测试往往是最后一个环节,风险较大,“怎么实现降低风险提高人效,测试用例可以复用”变成了我们这个阶段的主要工作。之前的流程是开发完成提测,做一次冒烟。因为我们的产品是互联网金融 APP,APP 有服务端开发和前端开发,像 web、wap、anroid、IOS 等渠道,在研发过程中经常会出现以下场景:
- 需求只是项目中的一小部分,测试问产品要不要全量测?产品担心这次需求的研发会影响到其他部分,就要求全量测试,于是测试的工期会拉得很长,拉长了需求的整个工期。
- 测试抱怨开发的 BUG 多,还有阻塞流程的 BUG,需要等待开发解决 BUG 后才能继续测试,导致整个测试工期加长。
- 手工测试偶有疏忽造成漏测试的点,需求上线后,客户反馈 BUG。
产品上线时间有 deadline;测试时间长,挤占开发时间;测试人手不够;测试的准确性达不到要求 … 要解决这些问题,必然要做自动化测试方案。
针对业务和测试开发同事的特点,我们从单元测试、接口测试、UI 自动化测试三个方面做了有效衔接和可持续使用的自动化测试方案。
服务端开发完成,接口测试开始介入。接口测试前期使用一些小工具,会在小工具里写一些脚本,来方便测试过程中的功能多次回归检验,是否有更好的方式来做这件事,于是我们搭建了接口自动化系统。之前测试是只对 UI 界面做功能测试,我们现在还实现了单元测试、UI 自动化测试、接口自动化测试。
第五阶段,测试团队全部人员转型测开,部分成员处在人工测试和自动化测试的边界上,实际上我们一直在做内训,让团队整体能更快地转型成为一个测试开发团队。这个阶段对成员要求相对较高,主要技术语言是 python,还要对基础的系统架构及运维知识有更多了解,团队内部正在开发测试项目看板、重写用例管理工具、升级接口自动化工具等,后期计划实现 APP 多设备管理及测试。还有一些测试没有提到,但也包括在主流程中,比如安全测试、兼容性测试、分辩率测试等。
目前项目的整体流程是这样的:
- 产品通过 DM 上传 PRD,参与人员熟悉需求。
- 开需求分析会议,确定需求最终版。
- 需求定稿后,开发人员抽象基础功能、编写 UI 部分,测试人员通过 testlink 写测试用例。
- 测试用例编写完需要产品、开发、测试人员做测试用例评审。
- 开发人员根据测试用例,编写自己具体业务的单元测试用例。前端人员和自动化测试人员制定 UI 自动化测试点,定义好断言字典和模拟用户行为的方法名称,自动化测试人员编写自动化测试 case。
- 开发人员开发的同时,接口测试人员根据接口文档,编写接口测试用例。
- 所有编码工作完成,开发人员单元测试通过后,进行接口测试验证,再进行 UI 自动化测试验证。UI 自动化测试既要测试当前需求点,也要回归以往的 case。
- 验证都通过后,手工测试人员介入。
- 手工测试完毕,自动化 CASE 反复测试通过的情况下,进行上线。
接下来分别介绍团队在单元测试、服务层自动化测试、UI 层自动化测试的具体技术实现。
二、单元测试
单元测试是对代码实现逻辑做测试,整体项目环节比较靠前,所以成本最小也最有效,但对开发人员的综合能力要求较高。
前端代码中,用户交互的部分交给 UI 自动化测试,而作为业务基础的类和方法,适用单元测试,我们项目使用测试库 mocha 和断言库 chai,配合开发工具 WEBSTORM,可以非常方便地检测代码通过性。比如我们开发的公用方法叫 tools.js,使用 mocha 来测试它的文件是 tools.test.js,如下图:
三、UI 自动化测试
UI 自动化测试的目标有两个:回归测试和测试准入,也就是开发完毕后,必须通过 UI 自动化的测试,方可进入手工测试阶段,以节省手工测试的工作量,缩短测试工期。
UI 自动化测试的难点在于产品多变,而 case 和 UI 是强关联,如果 UI 变更,就会导致 Case 失效。如何解决 case 的稳定性,使之不受 UI 的影响,成为我们的重要目标。经过反复尝试,我们选择了这样的方案。
测试工具对 dom 的选取,不再使用 ID 或者 XPATH,而由前端人员在页面上定义专门用于 UI 自动化的属性,测试工具需要的断言也由前端人员在场景触发时输出到页面中供测试工具抓取。测试工具和前端代码维护共同的字典,保证双方取值的正确性。我们在每个页面都有一个 ID 名为 assertWord 的隐藏 div,用来存放断言的值供测试工具抓取,用户不同操作的时候,会去更改这个值。
3.1 拿风险测评页举例
我们共用的字典如图:
进入页面的时候,会有
测试工具抓取到 riskPage,说明进入到了风险测评页。当用户勾选完选项提交问卷后,如果接口返回正确,前端代码如下:
我们在弹出结果的时候,去更改 assertWord 的值,供测试工具断言。
通过前端给测试工具抛值的方式,做到了 case 和 UI 的解耦。我们选择前端来处理的原因是:UI 改变也是前端来做,抛值也是前端来做,同一个人做相比前端和测试两个人做,避免了沟通产生的疏漏。
另外,对于用户操作的模拟,有时候测试工具不如前端编写方便,比如这个风险测评页面有很多道题目,测试工具要是模拟用户挨个答题,相当费时间,而前端则只需要很少的代码就能完成,如图:
所以我们编写了很多模拟用户行为的方法,供测试工具调用。
目前 UI 自动化测试已实现了 web 平台化,功能测试人员通过 web 页面来组织、编辑、执行 RFW(robotFrameWork)测试用例脚本,将测试用例的管理和执行统一到系统中。与传统的自动化测试相比,支持协同工作、分布式测试执行,提高了测试效率,同时也避免了功能测试人员在本地搭建一系列测试环境。
3.2 技术选型
1)web 框架:Flask
简述:Flask 是一个使用 Python 编写的轻量级 Web 应用框架。
优点:
- 轻巧,相较于大型框架 Django,flask 更适合小型 web 项目。
- 简洁,不需要复杂的分层和逻辑,框架内建了很多功能。
- 入门简单,即便没有多少 web 开发经验,也能很快做出网站。
2)分布式任务队列:Celery
简述:Celery 是一个分布式队列的管理工具, 可以用 Celery 提供的接口快速实现并管理一个分布式的任务队列。
优点:
- 简单,熟悉了 celery 的工作流程后,配置和使用还是比较简单的。
- 高可用,当任务执行失败或执行过程中发生连接中断,celery 会自动尝试重新执行任务。
- 快速,一个单进程的 celery 每分钟可处理上百万个任务。
- 灵活,几乎 celery 的各个组件都可以被扩展及自定制。
3)测试框架:Robot Framework
简述:Robot Framework 是一个基于 Python 的、可扩展的关键字驱动的测试自动化框架,用于端到端验收测试和验收测试驱动开发。
优点:
- 门槛低,通过使用关键字驱动测试(KDT)方法简化了自动化测试过程,方便测试人员创建易读的测试。
- 易于扩展,可以自定义测试库。
- 功能全面,支持 WEB 测试、SSH、telnet、API 接口多种测试方式。
4)UI 测试库:SeleniumLibrary
简述:SeleniumLibrary 是针对 Robot Framework 开发的 Selenium 库,它也是 Robot Framework 下最流行的库之一,主要用于编写 Web UI 自动化测试。
优点:
- 多浏览器支持,包括 Firefox、Chrome、IE、Opera、Safari。
- 多平台支持,包括 Linux、windows、Mac。
- 多语言支持,包括 Java、Python、ruby、PHP、C#、JavaScript。
3.3 平台架构图
3.4 各个功能模块
1)测试数据构造
测试人员可以根据测试需求获取测试数据,简化测试步骤提高测试效率。
2)Mock 服务切换
该模块为了满足一些特殊测试场景,将待测服务调用第三方平台的请求转发到 Mock server,以此来模拟那些服务,提供数据进行测试。
3)UI 测试脚本编辑
脚本的创建与编辑完全是通过页面操作的,平台展示页面清晰、简洁,支持协同工作。编辑页面仿照 Robot Framework 官方的 Ride 编辑软件,用类 Excel 表格的方式创建测试用例,同时支持关键字搜索、参数和使用提示,降低测试人员使用平台门槛。
脚本中使用的关键字分为两种:引用的 Library 和 resource。library 为第三方库,resource 为自定义关键字集合。Resource 关键字给我们提供的是一种类似于“函数”概念的用户自定义机制。我们可以将一些通用的业务过程封装为一个关键字。在编写测试用例时直接调用。一旦业务过程发生变化,我们只需要更改关键字中的业务逻辑即可,而不必更改每个测试用例。编写自定义关键字需要考虑它的健壮性、合理性,所以在任务的分配过程中这部分的编写都是由具有一定编程思想的测试人员实现的。
4)UI 测试脚本运行
测试执行需要选择脚本、测试环境和 Mock 地址 (可选)。运行过程中可以实时查看任务队列中的执行状态和历史任务的测试报告。
3.5 UI 自动化测试架构图
四、接口测试
接口测试主要的作用是提前降低风险,不至于等到 APP 端开发完成才发现问题,越往后时间成本和开发成本越高,风险越大。在多团队协作项目工期紧张的情况下,发现较大问题再调整产品需求几乎是不可能的,此类问题很消耗团队士气,团队被突如其来的问题影响,很容易被打乱节奏。在服务端开发完成提测,服务端测试可以有效拦截到一半左右的问题,很大程度降低风险,提高人效。
在我们的项目中具体实施步骤如下:
- 产品通过 DM 上传 PRD,参与人员熟悉需求。
- 开需求分析会议,确定需求最终版。
- 需求定稿后,开发人员抽象基础功能、编写 UI 部分,测试人员测试用例。
- 测试用例编写完需要产品、开发、测试人员做测试用例评审。
- 开发人员根据测试用例,编写自己具体业务的单元测试用例。前端人员和自动化测试人员制定 UI 自动化测试点,定义好断言字典和模拟用户行为的方法名称。自动化测试人员编写自动化测试 case。
- 开发人员开发的同时,接口测试人员根据接口文档,编写接口测试用例。
- 所有编码工作完成,开发人员单元测试通过后,进行接口测试验证,再进行 UI 自动化测试验证。UI 自动化测试既要测试当前需求点,也要回归以往的 case。
- 验证都通过后,手工测试人员介入。
- 手工测试完毕,自动化 CASE 反复测试通过的情况下,进行上线。
同样接口自动化测试也实现了 web 平台化,支持自动化测试全流程,覆盖测试环境管理、测试项目管理、测试脚本开发、测试执行、测试报告生成等流程。平台具有良好的扩展性、易维护性,支持异步执行、定时任务,能与企业邮件系统集成发送测试报告,同时在项目不断迭代的过程中,测试用例能弹性调整和复用。
4.1 技术选型
1)web 框架:Django
简述:最流行的 python web 框架,采用了 MVC 的框架模式,提供全套的 web 开发解决方案。
优点:
- 功能完善,自带大量的常用工具,可以快速开发。
- 开源框架,有完美的文档支持。
- 自带后台管理系统,只需要几行配置和代码就可以实现一个完整的后台管理系统。
- 路由映射,具有完整强大的路由映射功能,使用正则表达式使路由配置更加灵活、简洁。
- App 设计理念,App 是可插拔的,不需要了可以直接删除,对系统整体影响不大。
2)分布式任务队列:Celery
简述:Celery 是一个分布式队列的管理工具, 可以用 Celery 提供的接口快速实现并管理一个分布式的任务队列。
优点:
- 简单,熟悉了 celery 的工作流程后,配置和使用还是比较简单的。
- 高可用,当任务执行失败或执行过程中发生连接中断,celery 会自动尝试重新执行任务。
- 快速,一个单进程的 celery 每分钟可处理上百万个任务。
- 灵活,几乎 celery 的各个组件都可以被扩展及自定制。
3)测试框架:HttpRunner2.0
简述:HttpRunner 是一款面向 HTTP(S) 协议的通用测试框架,只需编写维护一份 YAML/JSON 脚本,即可实现自动化测试、性能测试、线上监控、持续集成等多种测试需求。
优点:
- 继承 Requests 的全部特性,轻松实现 HTTP(S) 的各种测试需求。
- 采用 YAML/JSON 的形式描述测试场景,保障测试用例描述的统一性和可维护性。
- 借助辅助函数,在测试脚本中轻松实现复杂的动态计算逻辑。
- 支持完善的测试用例分层机制,充分实现测试用例的复用。
- 结合 Locust 框架,无需额外的工作即可实现分布式性能测试。
- 极强的可扩展性,轻松实现二次开发和 Web 平台化。
4.2 接口自动化平台架构图
4.3 各个功能模块
1)项目管理
用例以项目为维度进行管理,可以对项目进行增、删、改、查。创建项目需要添加一些简要描述信息,在项目列表页面可以选择单个或多个项目运行。
2)模块管理
按照待测接口所属功能模块进行创建,支持模块的增、删、改、查。创建模块必须指定所属的项目,在模块列表页面可以选择单个或多个模块运行。
3)用例管理
支持用例的增、删、改、查,创建的用例必须指定所属的项目和模块。用例的整体结构包括局部变量定义、请求响应 hook 配置、请求接口 URL、请求数据、请求 Header、接口断言和接口返回值的抽取。
4)配置管理
配置内可定义全局变量和全局 hook,支持配置的增、删、改、查。
5)测试套件
通过测试套件,将服务于同一个测试目的或同一运行环境下的一系列测试用例有机的组合起来。支持测试套件的增、删、改、查。
6)Json Schema 管理
接口测试断言部分采用 Json Schema 进行 json 数据内容校验。每个接口对应着一个 Json Schema 的配置。支持增、删、改、查。
7)报告管理
支持测试报告的可持久化存储,可以在线查看、下载和删除。报告基于 extentreport 实现。
8)测试环境管理
录入新的测试环境信息,支持增、删、改、查。
9)用例执行
执行方式分为同步和异步两种,可以按照项目、模块、用例和测试套件执行。手动触发需要选择运行环境和执行方式,定时任务执行支持添加项目级别和模块集合,遵循 crontab 表达式。
4.4 接口自动化测试架构图 (引自官方文档)
作者:宜信综合理财研发部马宗泽、周政、黄雅哲
来源:宜信技术学院