还在手工写接口自动化用例?这种方式可以试试!
- 2019 年 10 月 8 日
- 筆記
故事的前奏
测试技术发展到今天,如果你还不会一些自动化技能,不会接口自动化方法,不会写一个两个框架,出去都不好意思跟人打招呼!
现阶段写接口自动化用例就跟以前写手工用例一样太习以为常了。那么有没有更加偷懒的方法,连接口自动化用例都省的写了呢?答案今天就揭晓!
好吧,我承认已经编不下去了!开始正经拿个小板凳来认真介绍了。这个故事还要从前阵子的一个项目讲起…
当时所在项目的“尿性”就是每次大版本上线,接口都可能是一次版本更新(用完即抛);如果按照正常思路去写接口用例来回归,可能用例还没有写完,项目就已经上线了。
但另一方面,考虑到之前该项目出现过接口类的BUG;所以不敢怠慢,即使在时间非常紧的情况下,还是希望能够覆盖到接口测试,尽最大可能的增加测试覆盖度。
所以最后就整出了一个同样“尿性”的接口自动化用例生成方案 — 录制+回放验证。每次项目录制一次,用完即抛,再来项目再录,用完再抛。
故事的GC
同样是录制,为了表现的更“骚”。我们也调研了多种方式:
•普通HTTP代理方式(mitmproxy、miniproxy、anyproxy)•基于HOST的代理方式(HProxy)•浏览器插件的方式(Chrome、FF)•TCPdump的方式(组装HTTP协议,不是人干的事情)
这几种方式,理论上都是可以完成HTTP协议的录制,并把请求和响应内容保存到DB,共日后来进行回放和验证。同时它们也是有各自特点的:
•普通HTTP代理,不能录制服务器之间的请求(比如:服务A访问服务B)•基于HOST代理,配置方式不够灵活,会影响系统全局的HOST•浏览器插件,同样只能录制浏览器的请求•TCPdump方式,组装太麻烦,不能跨平台
经过一番激烈的内心斗争之后,最后还是觉得怎么简单怎么来,选择了支持插件开发的普通HTTP代理 — mitmproxy。官方地址:https://www.mitmproxy.org/
这个代理是使用python开发的,所以天然支持python来开发插件,这也是我选择它的原因。并且它的插件开发不要太简单,只要编写一个常规的python文件即可。
在正式使用它之前,需要进行基础库的安装。windows的需要下载exe,linux下则可以直接通过pip install mitmproxy
来安装。下面就是官网的一个插件样例:
# anatomy.py from mitmproxy import ctx class Counter: def __init__(self): self.num = 0 def request(self, flow): self.num = self.num + 1 ctx.log.info("We've seen %d flows" % self.num) addons = [ Counter() ]
这里定义了一个类并实现了一个request
方法,最后把这个类注册到addons变量即可。这个插件用来记录一共有多少个request
请求经过了代理。可以通过以下命令启动代理:
mitmdump -s ./anatomy.py -p 8181
这里引用了anatomy.py
插件文件,并指定了监听端口为8181,不指定端口则默认会监听8080端口。启动成功之后,只要配置浏览器代理指向本地的8181端口即可,之后随便访问一个在线网页,你就会看到打印请求数的日志。
获取请求对象
前面样例只是简单的记录了请求数量,而如果想要录制接口自动化用例的话,则需要分别录制请求内容和响应内容。这里我们先看下如果获取请求内容。
# anatomy.py from mitmproxy import ctx class Counter: def __init__(self): pass def request(self, flow): request = flow.request data = { "url": request.url, "method": request.method, "headers": request.headers, "text": request.text,, "content": request.content, } ctx.log.info(data) addons = [ Counter() ]
重新启动执行命令,就会在命令行打印出每个请求的相关信息。
获取响应对象
有了请求信息,还缺少响应信息。获取的方式也类似,只要定义一个response
方法即可。
# anatomy.py from mitmproxy import ctx class Counter: def __init__(self): pass def response(self, flow): response = flow.response data = { "status_code": response.status_code, "reason": response.reason, "headers": response.headers, "text": response.text, "content": response.content } ctx.log.info(data) addons = [ Counter() ]
重新启动执行命令,就会在命令行打印出每个请求对应的响应信息。
过滤指定URL
默认情况下,插件会接收到经过代理的全量请求对象和响应对象。但实际情况我们不希望录制非接口的请求,比如:静态资源。这时就可以通过定制代理过滤规则的方式很容易的实现了。
# anatomy.py from mitmproxy import ctx class Counter: def __init__(self): self.filter = flowfilter.parse(ctx.options.dumper_filter) def request(self, flow): if flowfilter.match(self.filter, flow): # 是否匹配规则成功 ctx.log.info(flow.request.url) addons = [ Counter() ]
通过如下命令在重新启动脚本:
mitmdump -s ./anatomy.py -k -p 8181 ~u '^https://www.testqa.cn/static/.*'
此时再访问网页如果经过代理的请求,不是以https://www.testqa.cn/static/
开头的URL,则不会被打印出来,只有匹配这个正则的URL才会被打印。
接口用例录制架构图
基本的思路已经有了,这里再给一个完整的录制+回放的架构图,剩下的就等着你开干了!如果你想要获取完整的代码,那么请关注TestQA公众号并回复mitmproxy即可。
故事的结尾
故事开头我们已经讲过了,这个方案是一个用完即抛的方案。它有自己的一个适用范围,并不是所有项目都适用的,想要用在常规项目中,一定要能保证每次回放前能恢复原始测试环境。
另外使用这种方法,想要修改个别用例就会比较麻烦;所以录制的时候可以按相关业务,录制到一个集合中;修改的时候以一个集合为单位统一重新录制即可。