随着业务复杂度的提升,技术架构的微服务化已经非常普遍了,如何针对微服务化的产品进行测试,也有了很多的测试策略可以做选择,但是对于单体微服务的测试方案,却比较少有人提起。本文来聊聊这方面的测试策略。
01
文章源自玩技e族-https://www.playezu.com/297948.html
文章源自玩技e族-https://www.playezu.com/297948.html
如上图,从技术架构的角度上看,现在的多数产品是由前端组件 +Nginx 代理 + 各类微服务 + 数据层 + 系统层及一些外部依赖构成的。针对这个级别的测试策略,就非常的多了,本文暂不展开讲,后续再讨论。文章源自玩技e族-https://www.playezu.com/297948.html
如果把微服务拆开,只关注微服务之间的关联关系,这层是接口测试重点关注的对象。多个微服务通过 REST/RPC 协议进行调用,测试通过接口调用来模拟,完成对应功能的测试,也诞生了类似契约测试的方法论。文章源自玩技e族-https://www.playezu.com/297948.html
再往下拆分,针对单体的微服务,我们如何着手测试?大部分人可能就会归结为单元测试,因为到了这一层,很难有完整的业务需求被实现,测试难度也会大增(毕竟很多测试是不会看代码的)。从 ROI 上来说,效果可能会不理想。但如果做好了,对系统的可测试性和质量保障会有质的提升。文章源自玩技e族-https://www.playezu.com/297948.html
02
文章源自玩技e族-https://www.playezu.com/297948.html
文章源自玩技e族-https://www.playezu.com/297948.html
针对单体的微服务,可以从 4 个层次来做测试。文章源自玩技e族-https://www.playezu.com/297948.html
请求资源层:一般情况下在 Controller 层实现,这里关注的是服务如何对外提供服务,是 Rest 协议还是 RPC 协议?请求方法是否符合规范,还是只有一种 POST 请求?(关于 Post 请求和 Restful API 的争论,笔者更倾向于后者,但也不争论,看团队的情况)。同时,还要关注是否有鉴权行为。这里还需要关注一些非业务的请求处理,比如需要写到日志系统里的信息,其他非业务需要的接口(如健康检查、配置上报与获取之类的),这部分的测试往往很容易被忽略。如果出问题,在业务上也比较难被发现,甚至发现不了。文章源自玩技e族-https://www.playezu.com/297948.html
业务逻辑 + 数据处理:一般情况是在 Service 层和 Entity 层这里是业务逻辑处理的实体,大部分的业务逻辑都在这里被实现,这里也是我们常讲的单元测试的重点区域,目前支持单元测试的工具也非常的多,常见的有 Junit5,TestNG 以及一些框架自带的功能。单元测试除了是一种有用的测试策略外,还是一种强大的设计工具,尤其是与测试驱动开发相结合。文章源自玩技e族-https://www.playezu.com/297948.html
数据存储:指的是与数据库交付的场景,这里会见了的问题一般是数据连接不上,网络波动等。这种场景虽然很难出现和模拟,但我们需要对这些异常做充分的处理,以便当问题真的出现时,能够快速定位到。同时,为了程序的健壮性,也可以做出一些容错处理。
外部依赖:由于业务上的需要,每个微服务可能会去访问其他微服务,在这里,要注意避免网络隔离引起的错误(在容器化的部署环境下,网络问题更为复杂,需要特别关注),同时还要考虑网络延迟和中断引发的业务问题,需要被更优雅的处理,避免出现数据不一致的情况出现。特别是当依赖的内容不是本系统,而是其他系统时,更要注意数据一致性的问题。
03
有人可能会有疑问:有必要测试得这么细?业务测试都来不及,而且这些看起来和业务也没什么关系,不是一直强调交付价值嘛,这有什么价值?个人认为,细致的微服务测试对测试的价值有以下几点:
更清晰地了解业务实现:现在的微服务架构非常复杂,许多测试场景并不能通过简单的前端场景就能覆盖到,典型的业务比如查询,在以前,查询数据就是从数据库里来,但是现在,可以存放数据的来源非常得多,除了数据库,还有可能是 Redies,ES,文件等等,如果不了解这些实现,就很难去做针对性地覆盖;
更好的定位问题:测试人员还是应该学会如何更好地去定位问题,既提高了自己的能力,也提升了对团队的影响力,不好么?
避免遗漏场景:比如上文提到的请求资源和外部依赖,很难从更上层去验证,如果从单服务的角度来看,就很容易被验证。
更好地交流:与开发共同频的交流,而不是别人说什么你都不知道,也容易被忽悠。
提升自己的能力,拓宽自己的思路,这点就不细说了吧。
所以,在允许的情况下,多做一些这类的测试,也是个不错的选择。千里之堤,溃于蚁穴,质量的构建也是从这点点滴滴积累起来的。
但是这里也需要注意一点,并不是所有的单体微服务都需要这么认真的去测试,因为有些微服务的功能相对单一,或者是一些业务逻辑不是很复杂的服务,可以不需要过多的关注。在执行此类测试时,需要注意选择合适的微服务去验证。
04
关于单元测试,在整理资料的时候,遇到一个词:test doubles,说的是什么呢,指的是为了达到测试目的并且减少被测试对象的依赖,使用 “替身” 代替一个真实的依赖对象,从而保证了测试的速度和稳定性。这不就是我们常说的 Mock 吗?原来还是自己想简单了。
test doubles 一般会包含 4 类:Dummy、Fake、Stub 和最常见的 Mock。举一个简单的例子来说明下。
当我们有个业务需要访问通过数据库查询信息或者插入数据时:
Fake:我们可以直接 fake 一个数据库(现在很多 IDE 都会带)
Stub:我们向这个 fake 的数据库中插入 3 个数据,就可以直接获取这三个数据的返回值(可以理解为硬编码只返回这三个值)
Mock:插入数据时,我们只关注是否调用了插入数据这个接口,至于调用之后的预期结果是否正确,那不是我们关心的事,那是提供这个接口的人应该关心的事儿,
Dummy?Dummy 一般是直接定义一个对象就好了。
现在,你的思路是不是被打开了?测试是不是可以更好玩?
原文链接:https://mp.weixin.qq.com/s/smIQjVU1gpSD9wd44YievA
未知地区 2F
卷起来卷起来,生活不易,小猫咪卖艺~
未知地区 1F
学习了