接口测试 [讨论] 接口测试是否有必要自动生成 HAR 文件

扫地僧 · February 15, 2016 · Last by 思寒_seveniruby replied at February 16, 2016 · 4212 hits

看过一些帖子,觉得搞技术要有自己的一些想法。

这个功能本身很好,但更适用于控制层的测试(稍后详解),对于接口测试觉得意义不是很大,原因如下:

  1. 接口测试的前置性:接口作为偏底层的功能,一般是优先开发的,只要服务环境搭建好,就可以接口测试了;
  2. 接口测试的规范性:特别是用于给第三方调用,都要严格按照接口文档进行设计、开发、测试,所以接口测试脚本也要严格按照接口文档进行开发;
  3. 基于以上的原则:
    1. 如果截取app的请求来生成接口用例,再执行测试,违背接口测试前置性原则;
    2. 如果实际开发的接口和接口文档的定义不符,通过代理截取请求和响应并生成用例,这个用例本身就已经错了;

关于控制层测试,也就是分层测试中的web层测试(B\S的前端测试、app中的h5测试),就是把前端测试再次细分,隔离UI展现,把传统的前端脚本中的操作转化为页面请求的操作(可理解成未渲染的页面),并对之校验。以Java技术栈开发的产品为例,无论接口测试还是web测试,最终交互的还是servlet。所以个人觉得,自动生成HAR文件,更适合于控制层的测试,至于生成的格式是否必须用HAR标准,视具体情况而定吧。

以上纯属个人观点,不代表客观性。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 5 条回复 时间 点赞

估计是我最早在接口测试中提到这个根据Har生成接口测试的功能. 在我提之前, Gatling和其他的性能测试也已经支持通过Har生成各种类型的测试脚本了. 其他的LR等工具本身也是借助于已有的产品交互来截获数据, 本质也是一种事后补充的测试用例生成方法.

是不是Har不重要, 比如Nginx的带post的log也可以. tcpdump的数据也可以. 我还真的调研过可行性, 的确有工具能做到.
只要能抓到你测试需要的数据即可. 在可行的格式里面Har是最通用最简单的标准.
我选择Har是因为各种代理工具普遍都支持Har, 这样自己的接口测试框架也容易跟fiddler charles等代理工具配合使用.

理想情况下是接口规范是先出, 然后编写测试用例. 但是实际的情况是. 大部分的公司都是后补的规范和文档. 另外就是很多公司在推崇小迭代. 或者是为现有的系统补充测试用例保证回归. 所以大部分的接口测试都是后补的. Har等方式就能带来实际效果.
所以你的前两条假设和约定都不成立. 接口测试前置是比较好的, 但是这个理论不符合实践.

往长远看Swagger标准才是真的提出了接口测试前置的可行性方案. 在api设计的时候它能自动生成接口规范文档和接口交互模拟测试环境. 甚至是接口测试用例. 这个会是未来. 但是在目前更通用而简单的方案还是录制生成修改的方法

根据接口测试的经验, 是否前置, 是否足够简单也不重要, 重要的是维护成本. 如果能在极短的时间和极低的成本实现接口测试的编写和运行. 就足够好了. 比如有了自动生成接口测试用例的功能, 接口测试框架自身是否足够简单已经不重要了. 这也是gatling和lr工具的共同设计思路.

往大了说, 接口测试并不是描述的是Http接口, 他是一个广泛的接口, 不仅仅是某一层的网络接口协议, 还包括其他的"接口",
比如对servlet的调用, 对class method和api的调用, android activity的调用, android message的消息传递. 对gps的信号调用, 这些也都是接口. 找到一个可以方便定制和分析的接口层和接口维度都可以做接口测试. 我记得社区里面两年前还有人提过用am构造intent来测试activity. 这也是一种接口测试思路. 属于广义接口测试. 在单测之上还有好几层概念可以实践. 其他公司有在探索. 不过就目前来看. 对大多数的公司来说, http的接口测试是行业最成熟最标准的实践了.

#1楼 @seveniruby 如果是由于流程问题没标准文档,需要事后补充,这个我觉得可以,但是通过抓包(应该还要开发提供一个接口地址列表,进行过滤吧)生成的接口案例,测试角度来讲,总感觉缺少了点权威性,毕竟抓包抓的是开发写的代码发出的请求和响应,如果开发代码本身就是有bug的,何解?也就是说开发的代码不能既是球员又是裁判。
然后Gatling和LR主要是从性能测试的角度设计的,是在假设程序的功能正确的前提下考虑的,其自动生成的脚本也是如我所说的模拟用户操作的请求流,也就是V和C的交互,当然LR支持多协议,只要是符合其协议的接口也能测试。然而这些工具的设计初衷是性能测试为主,是在假设程序或接口正确的前提下进行录制的。

#2楼 @quqing 接口的正确性需要多方评估. 但是实际中这样的成本较大, 经验丰富的测试工程师只需要review下接口的交互即可. 分析Har的调用关系, 跟分析代码的调用关系类似. 都是一种review机制. 通过这个即可保证. 常常是在测试过程中, 所有人都觉得没问题, 而测试工程师通过抓取接口就能分析出一些潜在的隐患. 这个过程中懂接口正确性的其实只有研发和测试, 产品帮不上忙的.

开发的代码有bug会发生发错 不发 多发 解析错等各种情况. 无论有无bug, 我都会分析整个流程是不是出现了非合理现象, 进行评估.
也就是一个feature的交互流程里从输入触发开始, 到接口发出, 数据收回, 本地处理, UI渲染等整个流程都会被审核.

以至于现在我们组就算不做接口测试, 也会习惯的挂上拦截代理去分析整个交互流程. 确保每个环节都是对的.

code review本质是review了代码的流程和规范. Har代表的是接口的流程. 所以理论上讲, 这块应该也有个接口流程的review. 文档不靠谱, 规范也不靠谱. 就算他们都正确最后落地的实际还是可能有bug的代码. 在度量这个流程的正确性中, 貌似也只有Har完整保存了整个接口交互的证据.
Har只是http协议的典型代表, 任何印证接口流程的数据皆可代表, 比如api中的send receive log. controller和servlet的调用链记录, 代理工具, har, fiddler导出的curl命令序列等.

我也好奇的是, 为什么行业里面对Har这么重要的东西视而不见. 据我所知, 在任何正规的教科书中都不曾出现过这个概念.

#3楼 @seveniruby “以至于现在我们组就算不做接口测试, 也会习惯的挂上拦截代理去分析整个交互流程. 确保每个环节都是对的”,这点我非常赞同,我之前也写过分层框架实现该功能了,优点多多。
HAR是个标准,对于通用化确实非常好,特别是对于打算开源的工具。但实际应用中,可能有些场景需求其无法满足,可能有的人自定义一套内部标准,只要实现解析这套标准的方法即可。我之前也写过一套自定义的标准,是结合分层思想的,把部分内容裁剪掉了,也增加了部分内容,以下是demo:
{
"testcase": "layTestCase",
"scope": 7,
"dbDependController": true,
"uiDependController": true,
"useProxy": true,
"controller": [
{
"step": 1,
"url": "{internetAddr}inProduct/product.screen",
"method": "get",
"param": "productId=${productId}",
"postBody": false,
"encode": "GBK",
"proxy": "xx.xx.xxx.xx:8080",
"delay": 0,
"isDownload": "buy1"
},
{
"step": 2,
"url": "{internetAddr}login.do",
"method": "get",
"param": "date=#{UTC}",
"postBody": false,
"checkPoint": "\"code\":\"1\"",
"encode": "GBK",
"delay": 0,
"proxy": "xx.xx.xxx.xx:8080"
},
{
"step": 3,
"url": "{internetAddr}insProduct/saveChoices.do",
"method": "post",
"param": "totalPsn=2&childPsn=1&productPeriod=12&startDate=#{getDate(1)},
"postBody": false,
"regx": "idProduct={input type=\"hidden\" id=\"idProduct\" name=\"idProduct\" value=\"(.*)\"/>}#1,
"encode": "GBK",
"delay": 0,
"proxy": "xx.xx.xxx.xx:8080",
"isDownload": "buy2"
},

{
"step": 4,
"url": "{internetAddr}insuranceProduct/checkProdcut.do",
"method": "post",
"param": "idOrder=${idOrder}&idProduct=${idProduct}",
"postBody": false,
"encode": "GBK",
"delay": 0,
"proxy": "xx.xx.xxx.xx:8080"
}
],
"database": [
{
"refStep": 3,
"mode": "sql",
"dbName": "dbName1",
"queryParam": "${idOrder},${idProduct}",
"sql": "select id,amount from table where id =? and product=?",
"compareType": "content",
"dbAssert": "ID_PRODUCT=P004,AMOUNT=1"
},
{
"refStep": 4,
"mode": "proc",
"dbName": "dbName2",
"queryParam": "iiiooo,${idProduct},#{getDate(1)},2012-05-05,null,null,null",
"sql": "gs_package_calc.calc_sus_day",
"compareType": "content",
"dbAssert": "a,3,null"
}
],
"ui": [
{
"refStep": 1,
"chkImages": "tzlc,perINfo"
}
]
}

#4楼 @quqing 这个可以, 没问题的. Har只是个简单的json格式, 你自己做一套也可以的. 没必要纠结. 不过Har的好处是代理工具都可以跟他互相转换. 如果你自己做了, 可能需要自己编写代理工具才能实现Har和其他工具的数据导入导出了.

需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up