(“马蜂窝技术”公众号原创内容,ID: mfwtech)
一个项目从需求确定到最后上线,通常来说流程是这样的:
「测试」作为一个项目质量保证角色,在上面的整个流程中均有参与。而用例设计、项目测试环节更像测试的主场,PRD 的评审测试人员也会发表很多自己的观点,对项目的技术评审虽然测试人员也有参与,但也不如前两个环节的参与程度深。
其实,一个优秀的测试人员应该深入到项目的每一个环节中去发现问题,提出自己的观点,保证项目质量。那么要真正深入到项目实现中,测试应该怎么做呢?
一、Review 接口定义结构
接口定义文档在测试过程是测试人员接触比较多的设计文档,尤其是与最外层面向用户的接口设计相关的部分。在参加接口文档评审、编写接口用例这些场景下,测试人员都会仔细阅读接口设计文档。
通过接口文档,可以帮助测试人员清晰了解到前端与后断是怎么交互的,每个页面哪些操作与后端存在交互,不同的接口之间是否存在关联,清楚这些可以帮助测试人员在测试过程中对出现的问题进行精准判断,确定导致问题出现的范围。
在阅读接口文档可以关注以下几个方面:
- 接口中定义字段是否考虑了扩展性;
- 字段是否必须有明确的说明;如果是代码实现需要清晰定义 NotNull/NotBlank;
- 字段含义是否存在歧义,字段的含义要有明确的解释;
- 接口是否覆盖到了所有业务场景;
- 返回值结构、内容是否正确;通常返回值都有固定格式规范,返回值结构要规范统一,并且接口请求失败有明确的失败原因;
- 字段类型是否正确;
- 入参风格统一;比如日期格式如果是 yyyy-mm-dd 格式,每个接口最好都统一。
除了上面提到这些,在接口文档还要关注数据库表结构,确保表结构能满足接口需求;接口返回数据量要控制在一个合理的范围,返回数据量太大会有传输压力从而产生性能问题;接口之间要注意低耦
二、关注架构设计方案
对于测试工程师来说学习项目架构或者说系统架构是一个不小挑战,因为基本上所有的架构知识、开发框架都是基于开发人员进行设计的,而这些内容对于开发人员也是一个不小的挑战。
那测试人员为什么还要去了解学习?有测试同行曾经开玩笑说「了解项目的架构设计是为了在开会的时候听懂开发在说什么」。虽然是一句玩笑话,但也说明测试人员需要了解这方面的内容重要性。了解项目的架构设计可以在以下几方帮助到测试人员:
1. 培养测试人员的架构思维
因为测试环节不应该仅仅发生在提测后,在前期项目设计阶段也同样需要进行测试,只有通过对业务代码、架构设计、用到的技术有了解,才能够在设计阶段发现缺陷。
2. 帮助测试更全面、更有针对性地进行
比如性能测试,如果不清楚整个系统的架构,没办法对压测结果进行分析,甚至设计的压测方案可能都是存在问题的。还有就是在压测时候尤其互联网的系统架构压测时经常需要「预热」,需要预热的原因我们清楚吗?因为服务端会对数据进行缓冲。
比如在项目架构迁移时如何做到不漏测,拿火车票电子票从 PHP 迁移到 Java 的乘车人模块为例,迁移前和迁移后访问乘车人模块流程如下图所示。
1)迁移前电子票和抢票访问乘车人模块方式:
2)迁移后如下(黄色部分是这次迁移改动部分)
从流程图中可以看出,乘车人模块是抢票和电子票两个业务的公共模块,而此次迁移只有电子票的 App 调用 Java 接口访问乘车人,其他还是调用旧接口,所以乘车人模块重构后要保证电子票和抢票的两个端(App 和小程序)不管从旧接口还是从新接口访问功能都正常,就要弄清楚电子票和抢票这个两个业务哪部分做了迁移,哪部分没有迁移,技术方案设计是怎么样的,这样才能保证不漏测。
那测试人员应该怎么了解一个项目的架构呢?测试人员学习架构或者说了解架构设计应该有测试的独特视角,通常能做到清楚基本原理、了解被测系统部署架构、用到了哪些技术,从测试的角度调用到哪些接口就够了,当然如果能学习的深入更好。
首先,不管是已经上线的项目还是在正在进行中的项目,都有系统架构图,先从系统架构图入手,了解服务都有哪些,这些服务分布在哪一层,比如有面向用户接入层,中间处理不同业务的业务层服务,还有从外部服务获取数据外部接入层服务,还有数据存储、缓冲,不同层之间进行交互的协议、中间件都可以从架构图中看到,能帮助我们快速的对整个项目建立一个框架。
其次,查看服务之间的业务交互关系,明确业务数据流转。通过阅读流程图、泳道图、时序图都能帮助测试人员理清楚各个微服务之间的交互关系。下图是根据我自己对马蜂窝大交通抢票业务的理解,梳理的业务架构图:
另外,清楚业务状态机也很重要。熟悉状态机能帮助测试人员更加清晰的理解业务,需求文档是对业务功能的概括,状态机是对业务功能不同情况的分解。
最后,了解一些架构设计知识,比如为什么要用消息队列,好处是什么,在项目中不断积累架构相关的知识,架构相关的知识不断的丰满在进行项目设计方案评审时就可从测试角度提出问题,发现问题,对项目质量起到帮助,因为越早发现问题,损失越小。
三、关注数据库设计
数据库的重要性不言而喻,任何一条业务线都离不开。数据库表设计是否合理、是否考虑了业务扩展、是否考虑了读写分离等,都是需要测试人员在参加数据库设计评审,甚至在数据库设计时考虑的。下面分享一些在 Review 数据库设计表时的参考检查项:
1)不同表,相同含义的字段命名是否统一;
2)字段类型是否符合要求,比如数据量大的字段类型设计成 int,应该用 bigint 更合理;
3)字段长度设计是否合理;举例,曾经测试过一个功能,每 10 分钟查询 Redis 中 key 的值存到 MySQL 中,统计值和查询 key 分两列存储,字段长度设计是 60,实际情况是 key 的长度远远大于 60,对 key 进行截断存储,导致查询不到不结果。
4)字段是否为空;接口设计字段可以空,但是表结构设计字段 NOT NULL,与接口数据结构设计不一致,提交的时候显然回报错;
5)是否存在冗余字段;当然有些情况为了效率会允许冗余字段的存在;
6)是否需要分库分表。
除了以上提到的点,在数据库设计方面需要 Review 的内容还有很多,比如是否需要考虑读写分离、表之间的关联是否合理等等。建议大家去了解一些与数据库设计规则相关的知识,来帮助我们在 Review 或者参与数据库设计时发现更多问题。
四、阅读开发的代码
说到 Code Review 大家并不陌生,上线前分支合并 Master 要进行 Code Review,开发人员相互交叉进行 Review,研发同学常会听到这样的对话「飞哥帮我 review 下代码」。
Code Review 对于开发人员是很重要的 Check 步骤,对于测试人员也是一样,一个发现缺陷、理解项目的重要手段。阅读代码可以从以下几个方面帮助到我们:
1. 检查测试用例的遗漏点
我们都知道测试做不到穷尽测试,不管是做单元测试还是功能用例都不容易做到全部覆盖,尤其是有多个条件的情况下越不容易做到,Code Review 可以帮助我们再次检查是否测试中遗漏功能点。
2. 帮助测试人员更加熟悉系统,深入理解业务
黑盒测试的被测对象是已经成型的系统,不能清楚看到业务功能是在系统架构哪部分上实现的。比如现在流行的微服务架构,一个业务功能可能是多个微服务相互协作完成,通过阅读代码,能够清晰的知道业务实现的入口在哪里,调用了哪些服务,一个业务场景从开始到结束经过哪些环节都可以清楚地看到。
3. 发现增量功能 Bug 和设计缺陷
业务线的功能是不断迭代的,因提升体验而进行的功能优化和增加新功能都在迭代的范围内。测试人员面对是整个业务线,每次的迭代需要准确判断本次迭代影响的范围来确定测试范围。通过业务代码清楚具体的实现细节、实现方式,在业务功能迭代时,测试人员能准确的判断出代码增量是哪部分,关联受影响的代码是哪部分,确定测试范围,做到精准的测试,在设计评审时反馈可会产生影响的功能给开发人员,与开发形成良好的互动。
说了阅读代码的好处, 测试人员如何去 Review 开发人员代码?从哪几个方面入手?
1. 带着任务看代码
带着任务去看代码就是清楚本次迭代有哪些功能,最好在 Review 之前在熟悉一下测试用例,带着功能实现是否存在问题心态去看,关注业务逻辑实现、接口参数定义部分,一些配置的 config 实现可以不用关注,避免陷入到与功能无关的细节中。
2. 关注代码条件判断
实现业务逻辑各类条件的判断是必不可少的,也是容易出问题的地方,条件判断错误功能表现可能就是「失之毫厘,差之千里」。条件的判断需要结合业务实际情况,如:
(1)检查 if 语句中每个条件表达式是否正确。比如:变量取值 isNotBlank 和 isNotEmpty 就会导致不同结果,涉及与、或、非的表达式尤其要注意;
(2)检查条件表达式是否涵盖所有关联的变量。举个例子:一个订单状态流转和 a、b 两个变量的取值有关系,其中 b 变量在某些特情况下影响订单状态。如果在条件中只考虑对 a 的判断而忽略 b,就导致功能不完整。
在进行火车票的改签测试有这样一个 bug,同一个乘客成功购票后——> 将票改签到其他日期——> 再退票,然后这个乘客在买同样日期相同车次的票提示行程冲突,预期结果是:用户已经改签到其他日期并且退票,可以再次购买。下图是一个简化的流程图,判断是否行程冲突(黄色部分是导致 bug 的原因):
从流程图可以看出如果乘客有已出票的订单需要先判断是否出行或退票,如果否的话说明还是在出票状态,那需要继续判断是否进行了改签,如果已经改签允许用户继续创单,导致 Bug 的原因就是少判断了是否改签这个条件。
(3)检查对条件不同值给出的处理结果是否正确。举一个简单的例子:学生成绩不同区间对应 a、b、c 三个不同档有如下伪码:
If (s>=90):
Print「a」
Elseif (s>=80 && s<90):
Print「b」
Else:
Print「c」
上面的这段代码没有考虑 s 取异常值的情况,学生成绩取值是大于等于 0 的,还有就是成绩大于 100 时,在 c 档是否合理,也需要考虑实际需求。
3. 关注循环语句
所有的循环是否都有结束条件即所有的循环都能正常的结束;进入循环的入口条件是否正确即能进入到循环中;循环的条件是否存在越界的错误等。
4. 检查代码中接口定义与接口文档的定义是否一致
5. 针对增量代码进行 Review
通常由于时间有限,没有足够的时间阅读所有的代码,可以选择仅对对增量代码进行 Review,检查是否存在功能遗漏、改动代码对是否原有功能产生影响。
6. Review 后知识沉底
前面的几点都是再说如何去做,在阅读代码的过程中进行知识沉淀也很重要。在 Review 完成后,可以对发现的问题进行整理归类,在后面的测试过程中可以做为测试用例进行补充。Review 完成可以尝试画服务的流程图,项目架构图,帮助的自己对项目理解更深入。
7. 测试人员进行代码的反讲
阅读完代码后,测试人员反讲对代码的理解,可以邀请开发人员一起参加。
当然,我们在看到代码会碰到很多问题,可以向开发同学请教,了解代码结构,比如哪部分是业务实现代码,哪些是和数据库交互设计、哪些配置文件、哪些是接口定义文件,这些都可以帮助我们快速了解项目代码结构。
五、熟悉项目配置文件
为了灵活应对一些由于突发状况或频繁上线对业务带来的影响,在项目的实现过程中研发人员会把一些功能通过配置文件的方式去实现,比如流控配置、对不同业务场景的需求配置、为进行灰度测试的配置等,除此之外还有静态的环境配置。在配置文件内容的 Review 中应该关注的重点包括:
- 不同环境的配置文件不同,以防止将测试环境的配置同步到生产环境产生损失
- 功能配置开关,比如限流、降级服务开关、外部依赖如供应商的上下线
- 业务参数配置,业务功能的一些参数需要随时灵活配置,比如一些活动规则、临时性的通知信息
- 除了业务相关配置还有中间件的配置也需要关注,比如 tomcat、dubbo、mq 的参数设置很重要,对服务性能的影响非常明显。
测试人员深入到一个项目中,需要了解熟悉的远远不止我在上面提到这几个方面,还有很多,比如缓冲设计、缓冲失效时间设置,存储方式等,服务日志记录,随着对业务、系统架构的熟悉,这些都需要去了解,从而在测试中帮助到我们。
总结
上面是我对测试人员为什么要深入到一个项目实现中的,以及如何去深入的一些看法。测试作为项目最后一个环节,新的测试技术、手段、理念不断出现,但是保证项目质量的目标没有变。而深入到项目中,了解项目代码、了解项目设计对于一个优秀测试人员是必须具备的技能。当然,文中的内容也存在一些局限,欢迎其他测试小伙伴一起交流。
最后,马蜂窝大交通团队也在持续招聘中,测试、前端、Java 开发多个坑位,欢迎有意向的小伙伴来勾搭,简历请发送至邮箱:dongmin@mafengwo.com
本文作者:董敏,大交通研发团队测试工程师。