1 缘起

最近在负责测试的项目,相对来说比较复杂。从业务上来看,涉及商品添加、审核、交易、支付、退款、换号、管理等多个流程,从代码逻辑上来看,划分了 9 个模块,还涉及多个外部依赖。

所有 http 请求由网关层(Zuul)统一接受,进行权限控制和过滤后,根据不同的规则,通过 dubbo,转发到不同的模块服务。各模块之间通过 dubbo 接口调用、kafka 消息推送等方式进行通信,还有定时任务模块进行商品和订单状态的处理。

由于个人技术有限,负责这个项目的测试,是一个挑战,但同时,我发现这个项目也是一个很好的学习材料,代码中使用的大都是目前比较主流的框架和组件。

我刚开始看代码的时候好心累,因为基本看不懂,不了解 zuul、不了解 dubbo 调用,只能在网上搜索相关资料,结合代码去理解,实在看不懂的,就去请教开发,然后再继续看。

后来,我萌生了这样一个想法:“眼看千遍,不如手摸一遍”,学习代码中的框架、组件,如果都只是看的话,理解的深度终归有限,而且忘得快。我可以参照开发代码,然后把正在学习的框架、组件,以可执行小项目的形式进行实践,学以致用,加深理解。

然后我建了一个工程,取名为 CodeLearnAndPractice:代码学习与实践,以 Spring Boot 为基本框架,把学习的框架、组件,都作为该工程的子模块来进行管理,并写成 “代码学习与实践” 一系列的文章,以提升自己的技术水平。

2 深入了解代码的原动力

作为一名测试,如果只会黑盒测试的话,从工作本身来讲,工作容易陷于重复机械,且测试的深度有限;从个人角度来看,不可替代性太弱,工作带来的成就感有限。

测试的最终目的是保障产品的质量。了解系统的架构和运行的原理,才能根据系统的特性,选择合适的测试方法,而了解代码,是一切的根本。

了解代码,在遇到问题,能够快速定位问题,帮助开发同学更快速修复问题,并且可以增加开发对 QA 同学的认可度,以后沟通合作起来更方便。

而且被他人指出代码中的逻辑问题,会让开发在写代码的时候,更加注重代码的质量,提高自测的强度,在一定程度上提升代码的质量。

3 从实践,看测试深入了解代码的好处

了解代码对测试工作有好处,具体有哪些体现呢?下面我用几个实际工作中的例子,来说明一下。

3.1 提测前发现代码中的问题 -- 对照需求稿 review 代码实现,发现流程上的逻辑缺失

项目 Z,包含卖家添加商品、买家购买的功能,其中商品上架及下单都需要客服审核。

在集成测试方案设计阶段,我对照着需求稿和开发代码,用 xmind 梳理商品从添加到最后交易成功的过程中,所经历的十四种状态及每种状态下卖家在商品管理中可进行的不同操作。

在梳理过程中发现,在允许商品提交审核的状态列表中,没有包括交易审核失败(TRADE_AUDIT_FAILURE)的状态,这意味着,在商品的订单审核失败后,卖家希望重新出售该商品,编辑商品信息后点击提交审核,是会报异常的。

avatar

3.2 学习与实践相辅相成 -- 学习事务,并发现代码中的问题

平时工作中,我们要学习的知识很多,而个人以为,在实践中学习是最好的。

从自身的实践经验来看,如果单纯通过看书或看网上教程学习,而不能及时落地实践的话,学到的知识深度往往不够,而且容易忘记。

如果我们能够将学习的过程与项目实践相结合,二者相辅相成,学习的效率会更高一点。

我们在看代码过程中,可以学习开发代码的设计思路,例如模块划分、代码层次划分、异常处理等等,自己以后写代码的过程中可以借鉴这样的设计思路。

遇到不太了解的框架、组件等,可以去网上查阅相关资料进行学习,然后再回到代码,结合使用的业务场景,加深对所学知识的了解。

下面举一个事务的例子。在这个项目之前,没接触过事务,只是很久之前在网上零零散散看过一些介绍。一次跟开发讨论一个问题的的时候,开发提到这个地方使用了事务,可能保证不会出现问题,当时似懂非懂的。

后来做异常的时候,就跟 QA 同事讨论可以 check 代码中事务的使用是否正确,还可以学习和加深对事务的了解。

然后我们分工罗列出代码中所有的事务(使用@Transactional注解),挨个分析,发现有一个模块的事务的使用都不对,其中一个如下所示:

avatar

使用事务可以保证异常情况下数据的一致性。Spring 中,在方法上加@Transactional注解,方法执行抛异常时,就会回滚,数据库中数据也会回滚。该注解也可以加在类上。

一般,如果同时需要写库和调用其他服务时,应该先写库,再去调用其他服务,这样在其他服务调用失败时,数据库中数据也能回滚,避免数据的不一致。

3.3 发现黑盒测试难以发现的问题

上面列举的事务使用的问题,只有在特定的场景下才会出现,黑盒测试是很难发现和复现的。但一旦上线,生产环境复杂,一旦出发这种问题,定位起来还是比较复杂的。

测试对代码了解得多一点,就可以从代码的层次上,对容易出问题的地方让开发做一些梳理,尽量在上线前排除一些问题出现的可能性。

测试懂得越多,能测试的深度也就越深。

3.4 节省沟通成本,把时间用来定位问题,提升动手能力

如果 QA 同学不懂代码,发现问题后一般需要经历以下流程:
跟开发描述现象->常常还需要复现问题->开发看日志、远程调试,定位问题->反馈 QA 问题所在->修复并提交代码,QA 回归。

如果 QA 同学懂代码,发现问题后:
直接看日志、远程调试,定位问题->把问题代码位置直接反馈开发

这样就不用跟开发描述、复现问题,把节省下来的时间用来定位问题,充分利用问题排查的机会,可以进行远程代码调试,增加对代码的了解。

刚开始对项目代码不太熟的时候,定位问题所花的时间可能会长点,但一般几次之后,定位问题的速度就会蹭蹭地提高。

4 关于时间上的分配

可能很多人会有这样的疑问,平时测试任务太多,还要了解代码,时间不够用怎么办?

首先,测试中发现的问题,我们不用每个都去分析,挑一些看起来比较重要的,然后抽时间去排查,定位问题代码,这个不会花太多的时间。

其次,从自身的实践来看,想要比较快速地了解代码,最好是从核心接口的代码入口出发,然后一步步梳理整个处理的逻辑,调用的类和方法,以及他们所在的模块。看不懂或者看不下去的时候,可以在远程开一个调试端口,在本地进行单步调试,通过查看各变量的值,加深对代码逻辑的理解。关于远程调试的方法,可以参考我之前写过的一篇文章IDEA 远程调试 Java 代码实践及心得分享

到这里,代码学习与实践的开篇就写完了,后面会不定期更新实践总结,欢迎大家多多提意见和建议~~~
我刚开始的方向主要是把常用技术组件用代码实践出来,后面我会慢慢调整方向,把技术组件知识与测试工作结合起来进行学习和实践,在工作中学习,然后用学习的知识提升工作的质量和效率,是最终目标。

代码学习与实践系列

代码学习与实践:开篇 - 测试深入了解代码的好处及实践
代码学习与实践 (一):Spring Boot 多模块项目创建与配置
代码学习与实践 (二):Spring Boot 集成 Dubbo


↙↙↙阅读原文可查看相关链接,并与作者交流