关于软件质量保障,其实都是大同小异,去年 9 月份自己也根据公司的情况,总结了下来。
目录
一. 软件质量保障流程
二. 集成测试
三. 测试环境管理
四. 持续集成
五. 测试用例管理
六. 缺陷管理
七. 发布后管理
八. 结束语
微服务架构下,一个大型复杂软件系统不再是一个单体,而是一系列相互独立的微服务,特点鲜明:
由于每个服务都有对外暴露的接口,而且服务之间还可能互相依赖,直接导致:
这使得在敏捷交付的模式下,测试工作挑战巨大。如何能在「周」「天」甚至「小时」的发布周期下,进行高效的测试,是微服务架构产品的测试中常常思考的问题。
在产品的发布周期中,所有角色的联系相当紧密。每个角色有自己不同的职责,但最终都是为产品质量负责。
除了按照「需求->编码->测试→发布」常规的顺序交流外,不同角色之间也随时交流信息。
无论是外部需求,还是内部反馈,都会被一一记录,供下一轮迭代评审。每一次迭代之中包含着无数局部迭代,由大家一起评审需求变更和承诺交付。
整个产品质量保障全流程从需求开始,一直到交付上线,全流程如下:
需求评审 → 编码 → 单元测试 → 代码扫描 → 构建镜像 → 部署测试环境 → 接口自动化测试 → 端到端自动化测试 → 提测 → 手动测试 → 发布 → 上线
利用 Jenkins 对接 JIRA、Git、SonarQube、Registry 等各种工具实现 CI/CD,让工程师不再把时间和精力花费在构建、测试环境搭建和自动化测试执行这些重复性操作上。
通过提交代码自动触发流水线,进行单元测试,然后通过 Sonar-Scan 进行静态代码扫描,达到要求后会构建容器镜像,构建完成会自动部署测试环境,并触发自动化测试,测试通过后即可打上标签进行正式提测,在此之前的阶段都是通过自动触发,工程师只要把主要精力均放在结果上,待测试验证符合要求后,镜像才会最终发布并上线。
接口测试通常分三步走:
准备测试数据 → 对被测接口发起请求 → 验证返回结果
测试数据是一个非常重要的输入,在接口不变的情况下,利用大量的数据驱动测试,从而实现较高的覆盖率。
通常我们使用命令行工具 cURL 或者图形化界面工具 Postman 对接口发起请求,无论哪个工具,都需要对返回结果进行断言以判断是否符合预期。
验证返回结果不仅仅是验证返回的状态码,还要验证返回值,返回值的准确性则需要通过查询数据库等方法进行验证。
另外,我们通过 Swagger 来管理接口文档,以力求不同的开发人员发布统一标准的接口文档,供大家使用。
通常,接口是提前定义的,且不轻易变化,比较稳定,因此测试工程师可以根据定义好的接口文档,在开发编码的同时,实现接口自动化测试脚本,提高未来的测试效率,并且可以实现测试前置。
我们基于 Pytest 框架以及 Swagger 3.0 标准封装改造出一款轻量级接口自动化测试框架,自动解析接口文档并且生成能被 Pytest 驱动的测试用例结构,工程师只花精力编写测试数据。
接口自动化的实现本不难,主要难在测试数据的准备和返回值的验证。
每次都使用相同的测试数据一定是不合适的,因此,测试数据需要有一定的自动生成能力。
而返回值有很多是测试过程中才能生成得知的,如 UUID ,这类数据的验证需要实时去数据库获取。
模拟用户场景,进行基于消费者契约的业务主流程端到端测试,覆盖用户触发频率最高的操作。比如以电商举例:
登录 → 搜索产品 → 选择 → 加入购物车 → 提交订单 → 确认支付 → 收货确认 → 添加评论 → 搜索订单
这种测试通常可以在时间有限的情况作为最基础的验证,以确保没有阻塞性问题,保证用户体验。
但一个产品的业务主流程通常不会发生太大变化,是一项不断重复的工作,因此,我们优化了测试操作流程,从而实施自动化。
无论是 PC 端 Web UI 还是移动端应用 UI,现在都有比较成熟的自动化测试解决方案。对于 Web UI,我们期望其能够在容器中执行,所以选择了基于 Python 的 Selenium 调用 Headless Chrome「无头浏览器」,采用以关键字驱动的 Robot Framework 框架实现自动化测试。
WebUI 的操作主要是在页面输入和点击,因此我们采用 PageObject 设计模式封装页面元素,以此达到灵活使用关键字的拼装实现产品业务页面操作。
当页面出现错误,或非预期结果时,除了打印详尽的日志,还会自动截图插入到 HTML 的测试报告中。
我们所有的微服务均由流水线通过 Docker 构建出容器镜像,推送到独立的镜像仓库中。
为了减少测试过程中脏数据的干扰,有些服务器是需要全新安装的。
除此之外,通常产品都是支持多种平台的,因此也需要在多平台上进行安装测试,并且需要按照交付文档中的安装方法进行验证。
考虑到迭代周期短,应用场景复杂,准备全套测试环境还是需要花费不少精力,所以我们采用自动化的方式来管理和部署测试环境,并且 VM 和 Docker 容器并存。
对于相对稳定的测试用第三方服务器,直接使用 VM 搭建,不需要特别的维护;一些用于产品的中间件或需要常常清理的测试用服务器,除了使用 ESXi Server 的 VM 快照回滚,还会结合容器化部署,测完即删。
这些操作都通过自动化脚本执行,并且由流水线根据需求自动触发。
单元测试是产品质量检验的第一道关卡,其重要性和高效性不言而喻。单元测试做得好,会大大降低返工成本。单元测试除了关注通过率,还会在执行后通过 Sonar 分析出覆盖率,两者结合综合参考。
我们利用 Sonar-Scan 对所有代码进行扫描,并在 SonarQube 上设定一定的质量门限,达到质量标准的才会被标记为「通过」返回到流水线状态。
微服务产品的各个组件都是以容器镜像的形式构建发布,推送到指定镜像仓库。我们直接在流水线中进行 Docker 构建并推送。
检测到有指定版本新镜像生成,就会开始自动部署测试环境,并以无人值守的方式进行预测试。
通常我们把自动化测试前置到提测前,以此作为是否达到提测要求的快速验证。
测试通过后,会邮件通知到相关人员,正式作为 RC*「发布候选版本」* 提测。
我们使用 JIRA 的 Zephyr 插件管理测试用例,若干测试用例通过模块和标签进行筛选分类。
通过 Zephyr 的测试循环来做测试计划,每轮发布中包含若干循环,一次循环相当于一次迭代。
每次迭代会关联具体的测试用例集,新功能和回归通过不同目录分类。
Zephyr 可以追踪出已分配用例的执行情况。
我们把测试用例按照功能模块进行分类,由于测试用例在 JIRA 中没有目录结构,因此需要靠标签来筛选。
另外,针对不同类型的测试用例,我们也做了特殊的标签,如 API、E2E 等等。
Zephyr 在每一轮发布中可以包含多个测试循环,一次循环相当于一次迭代。
在每个迭代中,我们关联了计划执行的测试用例,并根据分类归在不同的目录中。
测试循环可以实时获取测试用例执行情况,若测试用例执行状态为「失败」,我们会关联一个 JIRA Issue。
另外,为了让所有人都看到直观的看到测试用例的执行与状态,我们利用 Grafana 定制了一个看板,使得测试结果可视化,让大家对产品质量有一个感性的解读。
一份完整的测试报告,包含:
摘要总结
一句话总结本轮迭代测试的结论
代码改动范围
新功能
缺陷修复
测试版本
镜像名
镜像版本
测试环境信息
服务器名称
服务器版本
缺陷验证
新发现
已修复
已验证
测试详情
新功能验证
回归测试
性能测试
安全性测试
缺陷的管理都在 JIRA 中完成,对于缺陷的发布,我们有着严谨的格式。除了填入 Sprint 信息供相关人员追踪外,还额外要求填入一些必要的标签,以标注缺陷发现的迭代周期、缺陷的类型、缺陷的功能模块,作为经验教训总结时的数据分析。
我们要求的必填项
- 项目
- 问题类型
- 主题
- 模块
- 描述
- Sprint
- 优先级
- 标签
开发工程师领取到属于自己的缺陷后,将其拖入「处理中」,修复自测后再拖入「待验证」交由测试工程师做最后的验证,并留下关于该缺陷的备注,如根本原因、解决方案等。
测试工程师验证时会填写详细的验证环境和步骤,有利于若问题重现,可找到历史记录进行分析。
利用 JIRA 的冲刺看板追踪每个缺陷的当前阶段,在测试交付前应该都在「已验证后关闭」的状态,非问题的 ISSUE 一般不会很多。
除了利用 JIRA 自身的看板,我们还利用 Grafana 增强了在当前冲刺期内的多样趋势图,以便于所有人都对一个周期内的进度有个直观感知,并且针对每个新功能也展现缺陷状态,这些数据都将作为本轮迭代软件质量的评估数据源之一。
对于缺陷的追踪,我们更关注在产品发布后,如何利用这些历史数据来提升未来的软件质量。
每轮迭代有一些正常规律,比如缺陷数量通常在前两个发布候选版本较多,相对复杂的新功能产生的缺陷数量会相对较多。
若出现后期某个候选版本缺陷数量突然增多,则要考虑产生该现象的原因,在发布前,就要考虑重新评估该原因带来的影响。
而对于没有产生任何缺陷记录的代码改动,同样要引起注意,需要评估测试的覆盖程度和深度。
所有缺陷的来源通常有:
每种来源都将作为软件质量不同的改进方向。
而对于缺陷的类别,比如:回归、新功能、偶发、概率等等。
也是我们分析的一个方向。
其中回归问题是我们特别关注的,同时也是最影响软件质量信心的一种。
每轮发布之后,需要对回归测试的范围进行更新,以增加新的覆盖点,主要的来源有:
回归测试是一个非常尴尬的测试范围。
理论上来说,回归测试不应该出现执行失败,所以很多时候,回归测试是增强软件质量信心的一种手段。
但回归测试的范围是不断扩大的,每一轮的新功能测试范围,必然会有一部分会归纳到下一轮的回归测试范围内。
因此,回归测试的范围就像一个永远滚不完的雪球,越来越大,越来越重。
接口测试是回归范围中最容易实现自动化,并且投入产出效果最佳的测试范围,并且实现接口测试自动化的最佳时期就是开发过程中。
但仍然还有相当多的测试用例是需要多花点精力才能实现自动化的,因此在产品发布后,我们都会对这些遗留的可自动化测试用例持续的实现。
软件质量是产品的血液,需要整个团队共同保障,特别是在 DevOps 团队中,成员的职责逐渐变得模糊,更应人人关注。
以上是一个比较通用的全流程,具体细节需要根据自身产品特性做调整。