还在手工写接口自动化用例?这种方式可以试试!

  • 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即可。

故事的结尾

故事开头我们已经讲过了,这个方案是一个用完即抛的方案。它有自己的一个适用范围,并不是所有项目都适用的,想要用在常规项目中,一定要能保证每次回放前能恢复原始测试环境。

另外使用这种方法,想要修改个别用例就会比较麻烦;所以录制的时候可以按相关业务,录制到一个集合中;修改的时候以一个集合为单位统一重新录制即可。