接口测试 小红薯们是如何调试 HTTP API 接口的 ?

法布雷加斯 · 2016年09月18日 · 最后由 ruanjiancaipu 回复于 2018年09月12日 · 69 次阅读
本帖已被设为精华帖!

遇到的困扰

接口测试对于大多数的公司来说,基本是一个常规武器,我们也在 Testerhome 的社区中学习到了很多同学分享出来的接口测试框架。不过除了平时使用 Jenkins 做接口的持续回归之外,我们的产品测试同学也会经常需要对一些接口进行一些手工的操作,CRUD 等等。目前业内有一些比较主流的接口测试工具,例如:

  1. Chrome + Postman
  2. Firefox + Rest Client
  3. Mac 下的Paw (商业)
  4. JMeter

上述的工具都可以完成基本的 HTTP 请求,并且支持标准的 HTTP Authentication 以及对于 HTTP Header 的操作。但是我们的接口有一些特殊,需要对于每一个 URL 进行一个签名的操作。如果 signature 是一个函数的话,那么输入的参数就是时间戳 +URL ,输出就一个 signature 字符串,并且需要添加到 HTTP 头中作为一个校验字段。这样就意味着每一次请求都需要去计算一次 signature。


我们想过的一些方案

  • Signature 生成器

写一个 Python 脚本来专门计算 Signature,然后产品同学把脚本输出的结果填写到 Postman 中的 HTTP Header 头中来发请求 。想想这个效率实在是太低了,直接放弃。

  • JMeter + BeanShell

JMeter 是一个压力测试工具,不过我们也看到有一些团队用它来做一些接口测试的工作。BeanShell 是 JMeter 支持的一个脚本语言,可以用来在 HTTP 请求前后做一些操作,例如修改请求参数,和 HTTP Header 头等。我们可以考虑把我们计算 Signature 的方法写在一个 BeanShell PreProcessor 中,这样就每次发送请求的时候,自动计算签名了。但是考虑到很多同学都没有使用过 JMeter,还有培训和掌握新工具的过程,所以还是放弃了。(充分考虑了产品测试小红薯们的对新测试工具的接受程度)


最终的解决方案

观察了很久后我们发现,其实小伙伴们都喜欢用 Chrome + Postman 的 Extension 来做接口的调试工作。那看来最好的方法,就是给他们发布一个新的 Chrome Extenstion 就能解决问题。当然我们不需要重头开始写,我们要做的就是在巨人的肩膀上加一个计算签名的功能。不过令人伤心的是 Postman 不是一个开源的项目,好在我们最后在 Github 上找到了这个项目ChromeRestClient, Chrome 上另外一个很流行的 Rest Client 插件。

如何做 Chrome Extension 开发我们就不在这里详述了,有兴趣的小伙伴可以移动到这里 Chrome Extension Development

ChromeRestClient 项目比较庞大,项目结构如下,

但是其中实际和 Chrome Extension 插件相关的目录是

  • app, 存放 ChromeRestClient Extension 核心代码的地方
  • branding, 存放 icon 的目录
  • tasks, 存放 gulp 项目 task 的目录,使用 gulp.js 来做 build
  • build, 只有在运行了gulp build以后才会出现,有 4 个 level 的 build,分别是 dev,stable,canary,beta
  • gulpfile.js, 根目录下的 gulpfile.js, 管理所有的 gulp task

搭建开发环境的过程很简单,只需要本地有安装 nodejs 即可, 我们使用的版本是 6.3.1, 接下来只要把项目从 github 克隆下来以后,在根目录下运行 npm install && bower install,就会在 app 目录下下载对应的依赖了。当然整个过程自然不会那么的一帆风顺,我们给社区反馈了 3 个 issue 并得到了开发者的及时反馈。

安装完依赖以后,使用 Chrome 浏览器,打开 Menu->More Tools -> Extensions, 选择Load Unpacked Extension, 然后选择 app 目录即可把本地的 extension 加载到 Chrome 中进行调试, 确保 app 目录下有manifest.json文件,这是一个 Chrome Extension 的描述文件

接下来就可以在 Chrome 中进行插件调试开发了,如果本地修改了代码,需要在 Extension 菜单页面中,选择 Reload,重新加载你的插件。由于 Chrome Extension 使用的是标准的 Web 开发技术,包括 HTML + CSS + Javascript,所以可以方便的在 Chrome Develop Toolbar 中进行 Debug 了。

ChromeRestClient 插件的页面是使用了 Google 的 Polymer 项目进行开发,这个和 AngularJS 类似,都属于 Google 在力推的 Web Component 技术。我们可以在app/elements/下找到一堆子目录,都是 Polymer 的 Plugin。当然我们最关心的是这个子目录arc-request-controller

我们可以看到arc-request-controller.js中,最核心的一个函数是sendRequest,

sendRequest: function () {
      if (!this.request) {
        StatusNotification.notify({
          message: 'Request not ready'
        });
        return;
      }
      if (!this.request.url) {
        StatusNotification.notify({
          message: 'Add URL to the request first'
        });
        return;
      }

      this._setIsError(false);
      this._setResponse(null);
      this._setRequestLoading(true);
      this._saveUrl();
      this._callRequest();
      this.showCookieBanner = false;
      arc.app.analytics.sendEvent('Engagement', 'Click', 'Request start');
      // Will help arrange methods bar according to importance of elements.
      arc.app.analytics.sendEvent('Request', 'Method', this.request.method);
    },

上面的代码中,大多数都是在做一些 Request Body 的初始化操作,最核心的是那句this._callRequest()调用,我们来看一下_callRequest的函数式怎么实现的


_callRequest: function () {
      // Copy the object so MagicVariables will not alter the view
      this._applyMagicVariables(Object.assign({}, this.request))
        .then((request) => this._applyCookies(request))
        .then((request) => this._applyAuthorization(request))
        .then((request) => this.fu(request))
        .then((request) => {
          // Make it async so errors will be handled by socket object.
          this.async(() => {
            if (this.auth) {
              request.auth = this.auth;
              this.auth = undefined;
            }
            if (this.useXhr) {
              this.$.xhr.request = request;
              this.$.xhr.run();
            } else {
              this.$.socket.request = request;
              this.$.socket.run();
            }
          });
        });
    },

接下来我们可以看到负责处理 HTTP Header 头的是_filterHeaders函数,那么我们只要把我们的签名算法写到这个函数里,并添加正确的 HTTP Header 就好了。在添加签名算法的过程中涉及到了一下 JS 的依赖,我们也统一用 bower 进行管理,并把依赖模块加入到了bower.json

最后我们使用 Gulp 来编译我们的 Chrome Extension,例如编译一个 beta 的版本 gulp build --target beta --build-only, 这样就会在 build 目录下创建一个 beta 目录,并把对应的 build 结果 copy 到里面。

有一个要提醒,如果有添加 JS 依赖的话,需要在tasks/builder.js中声明这个依赖

var bowerDeps = [
    'chrome-platform-analytics/google-analytics-bundle.js',
    'dexie-js/dist/dexie.min.js',
    'har/build/har.js',
    'lodash/lodash.js',
    'uri.js/src/URI.js',
    'prism/prism.js',
    'prism/plugins/autolinker/prism-autolinker.min.js',
    'js-md5/src/md5.js',
    'string-format-js/format.js'
  ];

万事大吉,接下来只要使用 Chrome 自带的 Pack Extension 功能把插件打包成一个.crx 的文件就可以分发给我们的产品测试同学了。(签名算法涉及到一些机密信息,所以我们没有上传到 Chrome Store 中)

希望这篇分享可以让你更好了解小红薯是如何在测试的工作中 think different 的,当然我们也更欢迎你加入我们的团队,和我们一起把测试变得有趣。有兴趣的同学可以看这篇招聘帖子,https://testerhome.com/topics/5045

共收到 24 条回复 时间 点赞

👍👍👍

很好的分享,很强的团队!

—— 来自 TesterHome 官方 安卓客户端

思寒_seveniruby 将本帖设为了精华贴 09月19日 04:38

加精理由: 描述和示例详实, 对开源工具进行定制化带来生产力的提升.

我们的对外 API 也是做了签名校验,不过我们的方式使用 JMeter + BeanShell 解决的!不过这种谷歌插件话更酷炫!

小红书?

signature 的脚本都写成这样了不如直接就用 request npm 写个轻量的 framework 了。还能直接连上 CI 跑。

#8 楼 @ccy 前面文章已经提到了,这个是用来给产品测试平时手工 Debug 用的工具啦。CI 的接口测试当然是每天跑 Jenkins 上的😀

终于看到了一个 rest client 的帖子,火狐也有 rest client 可以做接口测试的。

#11 楼 @silent_8 是的,之前选型的时候是考虑到了 Chrome 在团队中基本大家都在用,而且也在 Github 上找到了对应的开源项目,并且 Google 的 Chrome Development 的文档相对也比较丰富

一些愚见:
jmeter+beanshell 的方案可以考虑换成 jmeter 插件方案
扩展一个 jmeter 的前置处理器,测试人员的学习成本也比较低

#13 楼 @fforever14 不错的建议 . 之前也没有很深入了解过 jmeter plugin 的开发相关的东西,以后可以花点时间去研究一下。目前团队中是有一个独立的 Quality Tools and Infrastructure Team 来负责团队相关的工具和框架的开发维护工作,这个工具从需求提出,选型到最终交付,我们花了不到 3 天的时间,从学习成本的角度来看,是可以接受的。当然有一个客观的条件是,我们的 Software Enginneer, Tools and Infrastructure 的同学整体能力都还是很强的。

一个工程师文化很浓厚的团队,我们坚信是一定是一个有很强工具文化的团队。交付一个怎样的工具给到团队的其他成员,来充分提高他们的生产力,这是一个很值得探讨以及思考的话题。

#14 楼 @cesc 这个 team 很 googly。。

#15 楼 @andward 在 Googler 面前班门弄斧了

额,小红薯的接口测试就停留在这种阶段么

#17 楼 @jacexh 接口测试的持续集成是一直在 Jenkins 上运行的。这个工具是一个辅助的工具,用来帮助我们调试 API 的时候用的

只会 Jmeter 那种方案,感觉掌握了功能和性能都能测,性价比比较高~

#19 楼 @kesha0 因为这个工具另外一个目的是,也可以让开发同学一起使用,所以考虑到不是所有人都要学习 Jmeter 的,所以最后选择了 chrome 插件的方式。我们目前计划的 performance test 会基于 Python 来实现,因为整个团队的 stack 基本是 python 为主。但是如果单机 load 上不去的话,可能会考虑使用 gatling 的 akka,所以也没有准备未来用 jmeter 做性能压测的工作。

#20 楼 @cesc 我这边也是用 python 做性能测试,选用的是 locust,完全不用担心施压能力问题,单机不行还可以多机分布式部署

#21 楼 @jacexh 多谢分享,以后多交流

多谢分享!我们的接口也有签名还加密了。虽然平常在 Pycharm 里可以测试,但还是 Postman 用的爽,有时间改造下这个 Extension,定制化来用,那就方便快捷很多。

#23 楼 @tavisdxh 以后多交流,你也是上海的么?

仅楼主可见
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册