熟悉金字塔的同学都知道,整个分层在大的分类思想上分三层,除了单元测试层外,基于把另外两个层次分成客户端的自动化测试和服务端的自动化测试。基于客户端的测试使用最广泛的还是Webdriver框架,但是在快速交付的速度中基于UI的自动化测试收到各种局限,这种局限主要来自于维护的成本高和不可确定性,但是并不能说UI自动化测试没有它的价值,事实上任何一个测试的技术需要应用到合适的场景和环境中。在服务端的自动化测试体系中,可以分为工具类和代码类,工具类主要是PostMan和JMeter等测试工具,代码类比较广泛,如Java和Python等其他主流语言。服务端的测试相比客户端的测试方式,能够更加体现出测试的效率,不管是覆盖率的覆盖还是测试执行的效率上。
PostMan测试工具在工作中应用非常的广泛,几乎在工作中开发和测试都会使用到,在PostMan的测试工具中可以很好的处理要测试API的断言以及API基于业务场景的上下关联。PostMan也可以很好的把每个测试的case整合到一个collection中,这样导出collection后,可以和newman工具整合到一起形成命令行的执行,基于命令行就可以很轻松的和CI整合起来
JMeter测试工具可以做功能的自动化测试,以及性能自动化测试,其中做API的自动化测试很具备优势,在JMeter的测试工具中可以很轻松的分离测试的数据,测试的case之间的参数关联调用,测试数据的参数化整合,以及在JMeter中对cookie和请求地址很好的进行分离,完全的可以一套测试脚本就可以使用在多个测试环境中,需要做的就是在请求默认值里面修改下不同环境的请求地址而已,维护起来成本也是很低的,和ant整合后,很轻松的在CI整合起来,执行后形成基于HTML的测试报告以及性能测试报告,在JMeter的测试工具中即使有测试的case有1000+,它的执行速度也是很快的,基本5-7分钟就会出结果,很适合上线后的自动化测试回归验证和环境部署后的冒烟测试验证。
在Python的语言中提供了unittest和Pytest的测试框架,可以很轻松的把要测试的case整合成测试套件,然后批量执行所有的case,生成基于HTML的测试报告。这中间关于测试使用到的数据也是需要考虑处理的,其实在业务的立场上,重点需要清晰的知道输入是什么,然后中间处理,最后输出,我一直认为在API的自动化测试中,尽量的自己生产数据然后自己消费数据,这样在开始执行前环境是什么样,执行结束后环境还是什么样,当然中间会会涉及到业务逻辑的判断和处理。这样思考的目的是不需要刻意的为了自动化测试而造数据,造数据本身在成本上就很高,另外的点就是造的数据不一定就符合业务的场景和逻辑。基于这样的思考逻辑,我们可以把数据处理的分三个过程,其实刚才也有说过,只不过更加清晰化,它就是:输入--->处理--->输出。在基于业务场景的测试中,输入的过程其实本质上就是走基本的业务逻辑,随着测试点的执行创造测试数据的一个过程,而处理事实上就是再有了输入的前提的条件后,后面的业务场景的测试数据由于有了输入的过程,也就有了处理的数据,最终达到了一个完整业务链的验证和验证,也就是输出,达到了测试的目的和手段。这也符合思考过程的三个部分。
在自动化测试的过程中,既然有了PostMan,JMeter的测试工具,能够满足API的自动化测试,那么是否需要基于代码的自动化测试了,这是肯定的,因为工具并不能够满足所有的需求,工具不能满足需求的部分,就是需要代码去自定义来完成这部分。比如只想完善一个yaml的文件,期望就可以验证API,Tavern就可以很好的满足这个需求,如下的yaml文件:
test_name: Get some fake data from the JSON placeholder API
stages:
- name: Make sure we have the right ID
request:
url: https://jsonplaceholder.typicode.com/posts/1
method: GET
response:
status_code: 200
body:
id: 1
save:
body:
returned_id: id
---
test_name: 测试httpbin.org/get的响应时间
stages:
- name: 测试httpbin.org
#重试次数
max_retries: 1
request:
url: http://httpbin.org/get
method: GET
response:
status_code: 200
body:
url: http://httpbin.org/get
#---
test_name: test restful get token
marks:
- skip: this is a skip test
stages:
- name: get token
request:
url: http://localhost:5000/auth
method: POST
json:
username: wuya
password: asd888
headers:
content-type: application/json
response:
status_code: 200
---
test_name: webservice的请求
stages:
- name: get mobilecode
request:
url: http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx/getMobileCodeInfo
method: POST
data:
mobileCode: 13484545195
userID: ""
headers:
content-type: application/x-www-form-urlencoded
response:
status_code: 200
---
test_name: add book
stages:
- name: 多个断言信息
request:
url: http://localhost:5000/api/books
method: POST
json:
author: 无涯
done: true
name: API测试实战
response:
status_code: 200
body:
author: 无涯
name: API测试实战
done: true
#在响应中匹配任意返回值
id: !anyint
delay_after: 5
---
test_name: 查看编号为N的书籍信息
stages:
- name: assert test
request:
url: http://localhost:5000/api/book/1
method: GET
response:
status_code: 200
body:
status: 0
msg: ok
datas:
- { author: wuya }
delay_before: 3
#---
#test_name: 检查使用外部的函数
#
#stages:
# - name: verify_response_with
# request:
# url: http://localhost:5000/api/book/1
# method: GET
# response:
# status_code: 200
# verify_response_with:
# function: testing_utils.py:message_query_book
#接口之间的数据传递和值引用
到该文件的目录下,执行如下的命令,就可以很轻松的实现验证上面的接口信息,如下图所示:
这个过程中,并没有编写任何的一行代码,只是维护了一份yaml的文件,但是就可以验证上面对应的API,其实不会写代码,只需要懂得这一份文件维护的规则,也完全的能够做到自动化的测试。
谈到API的测试,那么针对API的测试,可以分为单个API的验证和基于业务场景的链路验证,单个API的验证,并不涉及到业务,只单纯的验证这个API是否满足业务方的需求,针对这样的API它的测试点主要为:
1、验证必填参数是否为空
2、验证参数的数据类型是否做了校验
3、验证参数的字段⻓度是否做了校验
4、接口的安全性校验和性能校验
前面三个都是很好理解的,主要是第四点,如何的来验证接口的安全性校验,特别是被测试的API是涉及支付,主要测试的点为
1、是否增加了反爬虫的机制
2、是否增加了请求次数的限制
3、是否增加了对应的请求头信息
3、是否增加了鉴权的认证信息(基本认证,常规认证,自定义认证)
4、是否对请求进行了加密
5、是否在被请求的服务端增加了IP的限制(白名单设置和IP的限制请求)
防止的手段很多的,就看在什么样的立场和什么样的环境下来使用,如果被测试的API即使涉及支付,但是产品基本没人使用,它的安全性校验是否有必要也是值得思考,但是从另外一个角度思考,既然是测试的API那么就有一定有它的用户,只不过用户数量的多少而已,从这个角度来说,不管什么样的测试技术,都得在业务的角度来思考问题然后制定它的测试策略和测试的方式以以及手段,如果完全的脱离了业务就显得有点空中楼阁了。
基于场景的很好理解的,这样的思考主要是基于产品完整链路的思考,在更加底层的维度思考,我们终究是在测试业务,只不过测试业务的过程中会使用到很多的测试技术来达到保障业务的按期交付和符合质量要求,那么基于业务场景的API测试可以理解为按产品的输入为主,最终达到产品的输出为标准,这个过程就涉及到业务场景,参数的关联性等。关于编写的模式,在API编写测试用例的文章里面有很详细的介绍。
不管是测试工具还是基于代码的测试方式,这些只是实现服务端测试的一个手段和过程而已,最重要的是需要理解它的本质和这个过程。在基于微服务的架构模式下,通常采用轻量级的通信方式(Rest AP,gRpc),这样的一个通信过程中包含了同步通信以及异步通信,也就是请求/响应和异步请求/响应(发布/订阅模式)。只所以需要详细的了解这个过程是因为不管是工具还是代码,我们需要清晰的知道请求地址,请求参数,请求头以及客户端发送请求后与服务端的交互,如常用的数据格式主要为:
在微服务的架构下,组件测试也是越来越广泛,同时契约测试的场景也是逐步的增加,基于消费者驱动模式下的测试,就需要使用mock的方式来解决这样的问题,很常见的场景是你要测试A功能,但是A功能的数据是B服务提供的,但是B服务瘫痪了无法启动,A功能的测试进度又不能耽误,那么只能mock数据来模拟B服务提供给A的数据来完成A的测试进度。
就单纯的在测试的角度考虑下,如果对一个产品的测试,在进行部署发布后,第一步进行冒烟测试,下来外部依赖API的测试,接着基于场景的API的测试,最后UI的自动化测试,这个过程中围绕一个点执行失败,就接着执行下一个点,如果一个步骤执行失败,那么后面的也就无法执行,执行失败的进行钉钉或者等其他消息通知到对应的人,这样的一个过程见如下图:
当然中间能够和开发打通,从提交代码开始一直到UI自动化测试结束,这个过程就完全的不需要人参与进去,那么剩余的工作就是自动化测试没有覆盖到的进行验证。
在《质量免费》的经典书籍中,作者谈到质量只所以不被认可,最主要是一个原因是对它进行度量,所以好与坏在本质上是没有区分的,比如第一份20个bug,第二月份10个bug,假设问题的级别都是一样的,但是没有去统计,那么在领导层面,第二月份和第二月份是没有区别的,都是存在问题的,这中间并不会看到研发团队的改善过程,就像《凤凰项目》里面最初是把所有的问题在墙上展示,但是后来墙上的问题越来越少,改善的过程也就很明显的,一目了然的能够看到,所以度量是一个非常重要的过程。比如覆盖率,完善了产品的百分比,节省了多少人力的投入等维度进行统计和度量。