一. 软件质量保障流程

1.1 微服务产品的特点

微服务架构下,一个大型复杂软件系统不再是一个单体,而是一系列相互独立的微服务,特点鲜明:

  • 每个服务独立,开发技术栈独立
  • 每个服务可以独立开发、部署、发布
  • 服务之间通过轻量级通信机制沟通,常用的是 RESTful API

软件质量保障全流程_测试用例

Micro Services

1.2 微服务产品测试的痛点

由于每个服务都有对外暴露的接口,而且服务之间还可能互相依赖,直接导致:

  • 接口数量翻倍增长
  • 测试场景翻倍增长

这使得在敏捷交付的模式下,测试工作挑战巨大。如何能在「周」「天」甚至「小时」的发布周期下,进行高效的测试,是微服务架构产品的测试中常常思考的问题。

1.3 软件质量保障全流程

1.3.1 角色

在产品的发布周期中,所有角色的联系相当紧密。每个角色有自己不同的职责,但最终都是为产品质量负责。

  • 产品经理 —— 管理需求和项目计划
  • 研发 —— 项目任务开发工作
  • 研发负责人 —— 研发团队管理及代码质量管控
  • 测试 —— 软件质量保障
  • 运维 —— 应用部署和运行管理

除了按照「需求->编码->测试→发布」常规的顺序交流外,不同角色之间也随时交流信息。

软件质量保障全流程_测试用例_02

DevOps Team

1.3.2 DevOps

无论是外部需求,还是内部反馈,都会被一一记录,供下一轮迭代评审。每一次迭代之中包含着无数局部迭代,由大家一起评审需求变更和承诺交付。

软件质量保障全流程_迭代_03

DevOps Loop

1.3.3 落地全流程

整个产品质量保障全流程从需求开始,一直到交付上线,全流程如下:

需求评审 → 编码 → 单元测试 → 代码扫描 → 构建镜像 → 部署测试环境 → 接口自动化测试 → 端到端自动化测试 → 提测 → 手动测试 → 发布 → 上线

利用 Jenkins 对接 JIRA、Git、SonarQube、Registry 等各种工具实现 CI/CD,让工程师不再把时间和精力花费在构建、测试环境搭建和自动化测试执行这些重复性操作上。

软件质量保障全流程_JIRA_04

Process

通过提交代码自动触发流水线,进行单元测试,然后通过 Sonar-Scan 进行静态代码扫描,达到要求后会构建容器镜像,构建完成会自动部署测试环境,并触发自动化测试,测试通过后即可打上标签进行正式提测,在此之前的阶段都是通过自动触发,工程师只要把主要精力均放在结果上,待测试验证符合要求后,镜像才会最终发布并上线。

二. 集成测试

2.1 接口

接口测试通常分三步走:

准备测试数据 → 对被测接口发起请求 → 验证返回结果

测试数据是一个非常重要的输入,在接口不变的情况下,利用大量的数据驱动测试,从而实现较高的覆盖率。

通常我们使用命令行工具 cURL 或者图形化界面工具 Postman 对接口发起请求,无论哪个工具,都需要对返回结果进行断言以判断是否符合预期。

软件质量保障全流程_JIRA_05

 

验证返回结果不仅仅是验证返回的状态码,还要验证返回值,返回值的准确性则需要通过查询数据库等方法进行验证。

另外,我们通过 Swagger 来管理接口文档,以力求不同的开发人员发布统一标准的接口文档,供大家使用。

软件质量保障全流程_JIRA_06

 

2.2 接口自动化

通常,接口是提前定义的,且不轻易变化,比较稳定,因此测试工程师可以根据定义好的接口文档,在开发编码的同时,实现接口自动化测试脚本,提高未来的测试效率,并且可以实现测试前置。

我们基于 Pytest 框架以及 Swagger 3.0 标准封装改造出一款轻量级接口自动化测试框架,自动解析接口文档并且生成能被 Pytest 驱动的测试用例结构,工程师只花精力编写测试数据。

软件质量保障全流程_测试用例_07

Mini API Test Framework

接口自动化的实现本不难,主要难在测试数据的准备和返回值的验证。

每次都使用相同的测试数据一定是不合适的,因此,测试数据需要有一定的自动生成能力。

而返回值有很多是测试过程中才能生成得知的,如 UUID ,这类数据的验证需要实时去数据库获取。

2.3 端到端

模拟用户场景,进行基于消费者契约的业务主流程端到端测试,覆盖用户触发频率最高的操作。比如以电商举例:

登录 → 搜索产品 → 选择 → 加入购物车 → 提交订单 → 确认支付 → 收货确认 → 添加评论 → 搜索订单

这种测试通常可以在时间有限的情况作为最基础的验证,以确保没有阻塞性问题,保证用户体验。

但一个产品的业务主流程通常不会发生太大变化,是一项不断重复的工作,因此,我们优化了测试操作流程,从而实施自动化。

2.4 UI 自动化

无论是 PC 端 Web UI 还是移动端应用 UI,现在都有比较成熟的自动化测试解决方案。对于 Web UI,我们期望其能够在容器中执行,所以选择了基于 Python 的 Selenium 调用 Headless Chrome「无头浏览器」,采用以关键字驱动的 Robot Framework 框架实现自动化测试。

WebUI 的操作主要是在页面输入和点击,因此我们采用 PageObject 设计模式封装页面元素,以此达到灵活使用关键字的拼装实现产品业务页面操作。

软件质量保障全流程_测试用例_08

RobotFramework 伪代码

当页面出现错误,或非预期结果时,除了打印详尽的日志,还会自动截图插入到 HTML 的测试报告中。

三. 测试环境管理

3.1 构建镜像

我们所有的微服务均由流水线通过 Docker 构建出容器镜像,推送到独立的镜像仓库中。

软件质量保障全流程_迭代_09

Harbor

3.2 测试环境搭建

为了减少测试过程中脏数据的干扰,有些服务器是需要全新安装的。

除此之外,通常产品都是支持多种平台的,因此也需要在多平台上进行安装测试,并且需要按照交付文档中的安装方法进行验证。

3.3 测试环境自动化运维

考虑到迭代周期短,应用场景复杂,准备全套测试环境还是需要花费不少精力,所以我们采用自动化的方式来管理和部署测试环境,并且 VM 和 Docker 容器并存。

对于相对稳定的测试用第三方服务器,直接使用 VM 搭建,不需要特别的维护;一些用于产品的中间件或需要常常清理的测试用服务器,除了使用 ESXi Server 的 VM 快照回滚,还会结合容器化部署,测完即删。

这些操作都通过自动化脚本执行,并且由流水线根据需求自动触发。

四. 持续集成

4.1 单元测试

单元测试是产品质量检验的第一道关卡,其重要性和高效性不言而喻。单元测试做得好,会大大降低返工成本。单元测试除了关注通过率,还会在执行后通过 Sonar 分析出覆盖率,两者结合综合参考。

4.2 静态代码扫描

我们利用 Sonar-Scan 对所有代码进行扫描,并在 SonarQube 上设定一定的质量门限,达到质量标准的才会被标记为「通过」返回到流水线状态。

软件质量保障全流程_测试用例_10

SonarQube

4.3 构建

微服务产品的各个组件都是以容器镜像的形式构建发布,推送到指定镜像仓库。我们直接在流水线中进行 Docker 构建并推送。

4.4 部署

检测到有指定版本新镜像生成,就会开始自动部署测试环境,并以无人值守的方式进行预测试。

4.5 自动化集成测试

通常我们把自动化测试前置到提测前,以此作为是否达到提测要求的快速验证。

测试通过后,会邮件通知到相关人员,正式作为 RC「发布候选版本」提测。

五. 测试用例管理

5.1 JIRA Zephyr

我们使用 JIRA 的 Zephyr 插件管理测试用例,若干测试用例通过模块和标签进行筛选分类。

通过 Zephyr 的测试循环来做测试计划,每轮发布中包含若干循环,一次循环相当于一次迭代。

每次迭代会关联具体的测试用例集,新功能和回归通过不同目录分类。

Zephyr 可以追踪出已分配用例的执行情况。

5.2 测试用例的分类

我们把测试用例按照功能模块进行分类,由于测试用例在 JIRA 中没有目录结构,因此需要靠标签来筛选。

另外,针对不同类型的测试用例,我们也做了特殊的标签,如 API、E2E 等等。

5.3 测试计划

Zephyr 在每一轮发布中可以包含多个测试循环,一次循环相当于一次迭代。

在每个迭代中,我们关联了计划执行的测试用例,并根据分类归在不同的目录中。

5.4 测试用例的执行状态

测试循环可以实时获取测试用例执行情况,若测试用例执行状态为「失败」,我们会关联一个 JIRA Issue。

软件质量保障全流程_JIRA_11

 

JIRA Zephyr

另外,为了让所有人都看到直观的看到测试用例的执行与状态,我们利用 Grafana 定制了一个看板,使得测试结果可视化,让大家对产品质量有一个感性的解读。

5.5 测试报告

一份完整的测试报告,包含:

摘要总结
  一句话总结本轮迭代测试的结论  代码改动范围    新功能    缺陷修复  测试版本    镜像名    镜像版本  测试环境信息    服务器名称    服务器版本缺陷验证  新发现  已修复  已验证测试详情  新功能验证  回归测试  性能测试  安全性测试

六. 缺陷管理

6.1 JIRA

缺陷的管理都在 JIRA 中完成,对于缺陷的发布,我们有着严谨的格式。除了填入 Sprint 信息供相关人员追踪外,还额外要求填入一些必要的标签,以标注缺陷发现的迭代周期、缺陷的类型、缺陷的功能模块,作为经验教训总结时的数据分析。

我们要求的必填项

项目

问题

类型

主题

模块

描述

Sprint

优先级

标签

6.2 缺陷的处理

开发工程师领取到属于自己的缺陷后,将其拖入「处理中」,修复自测后再拖入「待验证」交由测试工程师做最后的验证,并留下关于该缺陷的备注,如根本原因、解决方案等。

测试工程师验证时会填写详细的验证环境和步骤,有利于若问题重现,可找到历史记录进行分析。

6.3 缺陷的追踪

利用 JIRA 的冲刺看板追踪每个缺陷的当前阶段,在测试交付前应该都在「已验证后关闭」的状态,非问题的 ISSUE 一般不会很多。

软件质量保障全流程_迭代_12

JIRA Rapid Board

七. 发布后管理

7.1 缺陷分析

除了利用 JIRA 自身的看板,我们还利用 Grafana 增强了在当前冲刺期内的多样趋势图,以便于所有人都对一个周期内的进度有个直观感知,并且针对每个新功能也展现缺陷状态,这些数据都将作为本轮迭代软件质量的评估数据源之一。

软件质量保障全流程_测试用例_13

Quality Status

对于缺陷的追踪,我们更关注在产品发布后,如何利用这些历史数据来提升未来的软件质量。

每轮迭代有一些正常规律,比如缺陷数量通常在前两个发布候选版本较多,相对复杂的新功能产生的缺陷数量会相对较多。

若出现后期某个候选版本缺陷数量突然增多,则要考虑产生该现象的原因,在发布前,就要考虑重新评估该原因带来的影响。

而对于没有产生任何缺陷记录的代码改动,同样要引起注意,需要评估测试的覆盖程度和深度。

所有缺陷的来源通常有:

  • 测试发现
  • 开发发现
  • 客户现场

每种来源都将作为软件质量不同的改进方向。

而对于缺陷的类别,比如:回归、新功能、偶发、概率等等。

也是我们分析的一个方向。

其中回归问题是我们特别关注的,同时也是最影响软件质量信心的一种。

7.2 回归改进

每轮发布之后,需要对回归测试的范围进行更新,以增加新的覆盖点,主要的来源有:

  • 最近一轮期间新功能的验证
  • 最近一轮期间 Hotfix 的验证
  • 最近一轮期间客户反馈的问题
  • 最近一轮期间开发和测试新发现的缺陷
  • 由于对技术和产品的积累,测试主动新增的测试用例

7.3 测试用例自动化

回归测试是一个非常尴尬的测试范围。

理论上来说,回归测试不应该出现执行失败,所以很多时候,回归测试是增强软件质量信心的一种手段。

但回归测试的范围是不断扩大的,每一轮的新功能测试范围,必然会有一部分会归纳到下一轮的回归测试范围内。

因此,回归测试的范围就像一个永远滚不完的雪球,越来越大,越来越重。

接口测试是回归范围中最容易实现自动化,并且投入产出效果最佳的测试范围,并且实现接口测试自动化的最佳时期就是开发过程中。

但仍然还有相当多的测试用例是需要多花点精力才能实现自动化的,因此在产品发布后,我们都会对这些遗留的可自动化测试用例持续的实现。

八. 结束语

软件质量是产品的血液,需要整个团队共同保障,特别是在 DevOps 团队中,成员的职责逐渐变得模糊,更应人人关注。

以上是一个比较通用的全流程,具体细节需要根据自身产品特性做调整。