You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

127 lines
14 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 测试专栏特别放送 | 答疑解惑第四期
你好,我是茹炳晟。
今天的“答疑解惑”文章我将针对API自动化测试和代码级测试这两个系列6篇文章中的问题和你展开分享。
我还是会先简单概括下每篇文章的内容,并给出文章链接,帮助你复习相应的内容。同时,如果你再次阅读时还有哪些疑问的话,也欢迎你在文章下面继续留言。我会一直关注着你的学习情况,希望可以扫清软件测试精进道路上的障碍。
现在,我们就开始今天的主题吧。
## 问题一实际项目中往往会存在按时序的API调用以及异步API调用这类API测试要如何开展
在专栏的第22篇文章[《从0到1API测试怎么做常用API测试工具简介》](https://time.geekbang.org/column/article/13421)中我以基于主流Spring Boot框架开发的简单Restful API为例分别介绍如何使用cURL和Postman对其进行最基本的功能测试希望可以让你先对API测试有个感性认识。另外在这篇文章中我还和你分享了目前一些常见的典型复杂场景以及相应的测试思路和方法。
而在文章最后我希望你思考的是实际项目中往往会存在按时序的API调用以及异步API调用这类API测试要如何开展现在我来说说我的经验吧。
**我们先一起看看按时序调用的API序列的测试场景。**
对于此类测试我一般建议通过GUI操作来录制API的调用。比如在启用Fiddler的情况下通过GUI来完成业务操作随后去分析Fiddler抓取到的后端API请求顺序然后以此来开发API测试用例。
开发测试用例的过程中还需要特别关注前后两个API调用之间的数据传递比如需要将前一个API调用返回的response中的某个值作为参数传递给下一个API调用。
**其次是异步API的测试**。对于异步API测试的场景我们往往先会采取“只验证其是否发起了正确的调用而不直接验证操作结果”的方式。比如你的被测API是一个异步操作的API那么我只会去验证这个API是否按照预期发起了正确的异步调用请求而不会直接去验证异步操作的结果。如果这类测试全部通过后我们才会考虑真正验证异步操作结果的测试用例。
举个实际的例子假设你的被测API A完成的是下订单的操作。这个API A完成下订单操作要通过调用另外一个API B将订单信息写入到消息队列中去。而真正下订单成功指的是消息队列中的消息被后续服务正确处理并且成功了。此时这里的后续消息处理就是异步的操作了。
那么当我们要测试这个API A的时候我们只需要验证它是否正确地发起了对API B的调用即可而不用关心API B的具体行为结果。
也就是说我们只关注API A是否以正确的参数调用了API B即可而无需关注API B是否正确地执行了将订单信息写入消息队列的操作更不用关注消息队列中的消息被异步处理的结果。
注意这里的测试重点,应该更多地放在前面的部分,而真正验证异步操作结果的测试在资源有限的情况下只需覆盖最典型的场景即可。
## 问题二对基于配置文件的API测试框架你有哪些看法呢
在专栏的第23篇文章[《知其然知其所以然聊聊API自动化测试框架的前世今生》](https://time.geekbang.org/column/article/13565)中我和你分享了API自动化测试框架的发展历程帮助你理解API测试是如何一步一步地发展成今天的样子希望可以以这种“知其所以然”的方式加深你对API自动化测试的理解。
而在这篇文章最后我提到了基于配置文件的API测试框架比如典型的HttpRunner。在此类API测试框架的支持下测试用例本身往往就是纯粹的配置文件了。如果你用过这个框架的话我希望你可以谈谈你的看法。
对于基于配置文件的API测试框架的确是个不错的方向尤其是国内的开源框架HttpRunner更是推动了这种测试框架的普及。
**基于配置文件的API测试框架的优势可以归纳为以下三方面**
1. 降低了测试用例开发的门槛使得完全没有代码基础的同学也可以很容易地完成API测试
2. 可以很方便地将API功能测试用例直接转换成API性能测试的用例HttpRunner可以使用lucust直接实现这样的转换
3. 同时HttpRunner这类工具还支持直接从网络转发工具得到的HAR中提取API调用的测试用例进一步降低了API测试用例的开发成本。
所以基于配置文件的API测试框架很受初学者的欢迎。
但是为了完成一些复杂场景的测试用例设计以及复杂的结果判断你还是需要具备基本的代码能力以完成这些复杂场景的测试实现。比如HttpRunner就会涉及到使用debugtalk.py来实现hook函数的功能扩展。
也就是说完全不写代码的API测试只能覆盖大部分的简单测试场景如果你要搞定复杂场景的API测试的话你是要必须掌握一些基本的开发技能这里没有任何捷径可走。
另外很多读者的留言也很精彩我这里特地选取了两条供大家参考。从Cynthia的留言中我看得出她已经完全习得了这篇文章中描述的方法的精髓这也正是我想要传达给你的最核心的内容。
![](https://static001.geekbang.org/resource/image/a6/ba/a67715406c2a7ae6e9bb98d2e3198eba.png)
Martin在留言的后半部分中提到通过HttpRunner来实现轻量级的API测试的确是个好方法也最大程度地发挥了HttpRunner的价值。但是留言前半部分的“Postman转Python或者Java”的观点我并不是很认同。其实Postman是有直接代码转换功能的而且支持各种语言的各种框架基本可以实现一键操作所以其实很多没有采用HttpRunner的企业都还在普遍使用这个方法。
![](https://static001.geekbang.org/resource/image/5d/9c/5dc1be96cdacac1a510d10019e1cd59c.png)
## 问题三如果无法通过API Gateway方法得到契约的话应该采用什么方法来解决呢
在专栏的第24篇文章[《紧跟时代步伐微服务模式下API测试要怎么做》](https://time.geekbang.org/column/article/13581)中我和你分享了微服务模式下的API测试旨在帮助你认清庞大的测试用例数量、微服务之间的相互耦合这两个问题的本质以更好地开展测试。所以我今天分享这个主题的目的就是帮你理解这两个问题的本质以及如何基于消费者契约的方法来解决这两个难题。
而在今天这篇文章最后我希望你思考的是基于消费者契约的API测试中对于那些新开发的API或者加了新功能的API由于之前都没有实际的消费者所以你无法通过API Gateway方法得到契约。对于这种情况你会采用什么方法来解决呢
从我的经验来看因为缺乏契约所以还是会采用传统的API测试方法也就是根据API设计文档来设计测试用例。
这时我们采取的API测试策略是
* 对于已经上线的API我们会通过契约测试来保证质量
* 而对于新的API或者是加了新功能的API则还是采用传统的基于API设计文档来设计测试用例同时基于代码覆盖率来指导补充遗漏测试用例的方式来保证质量。当这些新API上线运行了一段时间后我们就会缩小测试的范围逐渐向契约测试过渡。
## 问题四:你所在公司,在进行代码级测试时,采用过哪些方法呢?
在专栏的第25篇文章[《不破不立:掌握代码级测试的基本理念与方法》](https://time.geekbang.org/column/article/14008)中,我根据实际工程项目中的实践,总结了五种常见的代码错误,以及对应的四大类代码级测试方法。这里我还想在多啰嗦一句,代码级测试的测试方法一定是一套测试方法的集合,而不是一个测试方法。
而在这篇文章最后我希望你分享一下你所在公司在进行代码级测试时采用过哪些方法又是如何具体开展的。这里我来分享下我在eBay的经验吧。
在eBay代码质量保障已经完全纳入了CI/CD流水线。
首先我们基于Sonar启用了静态代码。除了在上传Git的时候触发静态扫描外开发人员在本地IDE中也会进行实时的静态扫描并可以实时看到分析结果这样就可以在代码被递交到代码仓库前就已经完成了预检测。
其实,我们并没有直接采用标准的代码静态扫描的规则库,而是删除了其中很多我们认为过于严格的规则,同时加入了一些我们认为比较重要的检测项,使得这个规则库更符合我们的业务场景。一般情况下,这些规则的修订是由测试架构师牵头,与开发主管和资深的开发人员一起协商决定的。
这里需要注意的是我们并不要求静态扫描上报的所有错误都被修复后才能发布只要求解决最关键的问题即可。而对于那些所谓的Code Smell问题基于研发成本的考虑我们并不会要求完全修复。
接着CI/CD流水线会触发代码动态测试即单元测试。这里我们不仅要求单元测试能够100%通过并且会要求达到一定的代码覆盖率。在eBay我们对不同模块的代码覆盖率要求也不一样并没有一个硬性指标。其实这也是出于研发成本的考虑。
通常来讲,对底层模块以及提供公共服务的中间件的代码覆盖率指标的要求,一般都会比较高。而我们对前端模块的覆盖率要求,就会低很多。
## 问题五除了Sonar你还用过哪些静态代码扫描工具使用过程中遇到过哪些问题
在专栏的第26篇文章[《深入浅出之静态测试方法》](https://time.geekbang.org/column/article/14197)中我和你详细分享了人工静态测试方法和自动静态测试方法来帮你理解研发流程上是如何保证代码质量的。另外我以Sonar为例和你分享了如何搭建自己的自动静态代码扫描方案并且应用到项目的日常开发工作中去。
而在这篇文章最后我希望你分享的是除了Sonar你还用过哪些静态代码扫描工具使用过程中遇到过哪些问题。
其实优秀的代码静态扫描工具远远不止Sonar比如Fortify SCA和Checkmarx CxSuite等都是很优秀的静态扫描工具。至于使用过程中需要的问题我觉得主要有这么三个
**第一是误报率**。过高的误报率会降低开发人员对测试工具的信任度,而且还会引入很多人为标注的工作量。
**第二是规则库的完备性和实用性**。很多时候你会发现标准代码规则库中的一些规则设计不够合理有点教条主义。比如有些规则库会强行规定一个函数的代码行数不能超过200行从代码的模块化和易维护性角度来讲过长的函数实现体的确不利于代码健康。但是也不能完全一刀切毕竟有些函数就是实现起来比较复杂。所以很多时候我们需要对标准规则库进行深层次地裁剪以更好地适应企业的实际情况。
**第三是自定义规则的难易程度**。虽然很多静态代码工具都提供了规则编辑器,来方便你实现自己的规则,但是这些规则编辑器的使用方法和语法的学习成本比较高,对初学者不够友好。
## 问题六:在单元测试过程中,你都遇到过哪些问题,又是如何解决的呢?
在专栏的第27篇文章[《深入浅出之动态测试方法》](https://time.geekbang.org/column/article/14344)中,我和你分享了人工动态测试方法和自动动态测试方法。因为自动动态方法并不能理解代码逻辑,所以仅仅被用于发现异常、崩溃和超时这类“有特征”的错误,而对于代码逻辑功能的测试,主要还是要依靠人工动态方法。
在这篇文章最后,我希望你分享的是,除了我在文中提到的几个单元测试的难点问题,你还遇到过哪些问题,又是如何解决的。
这里,我想再和你分享我曾在单元测试中遇到过的问题。
**单元测试的难点中较为典型的就是对内部输入的控制**。对于内部输入的控制有数十种不同的场景,这里我就举一个例子,意在抛砖引玉。
首先为了达到较高的测试代码覆盖率如果代码中包括了if-else分支那么我们的测试就需要分别执行到这两个分支。假设现在有一个if-else分支是根据malloc这个内存分配函数的结果进行不同的处理如果内存分配成功了就执行A逻辑如果执行失败了就执行B逻辑。
那么在做单元测试的时候通常情况下很容易覆盖内存分配成功的场景但是想要实现“可控”的内存分配失败就比较困难了。因为malloc是个底层系统函数根本无法对其控制。
为了解决这个问题我们就可以采用桩函数的思想引入一个malloc的桩函数在这个桩函数的内部再去调用真正的系统malloc函数如果需要模拟真正的malloc函数的失败就在桩函数里面直接返回malloc函数失败的返回值来达到模拟真正malloc函数失败场景的目的。这样就能在被测函数中通过可控的方式来模拟系统底层函数的返回值了。
最后感谢你能认真阅读第22~27这6篇文章的内容并写下了你的想法和问题。期待你能继续关注我的专栏继续留下你对文章内容的思考我也在一直关注着你的留言、你的学习情况。
感谢你的支持,我们下一期答疑文章再见!