HttpRunner 300 行 Python 代码打造实用接口测试框架

debugtalk · 2017年06月28日 · 最后由 debugtalk 回复于 2017年08月20日 · 2190 次阅读

在刚开始实现ApiTestEngine的时候,@kasi 提议做一个 Java 版的。对于这样的建议,我当然是拒绝的,瞬即回复了他,“人生苦短,回头是岸啊”。

当然,我没好意思跟他说的是,我不会 Java 啊。不过最主要的原因嘛,还是因为 Python 的语法简洁,可以采用很少的代码量实现丰富的功能。

有多简洁呢?

刚在coveralls上看了下ApiTestEngine框架的代码统计行数,总行数只有 268 行,还不足 300 行。

当然,这个行数指的是框架本身的Python代码行数,不包括示例注释的行数。从上图可以看出来,LINES列是文件总行数,RELEVANT列是实际的Python代码行数。例如ate/runner.py文件,注释的行数是远多于实际代码行数的。

最极端的一个例子是,ate/testcase.py文件中的parse函数,示例注释行数 35 行,Python代码只有 2 行。

def parse(self, testcase_template):
   """ parse testcase_template, replace all variables with bind value.
   variables marker: ${variable}.
   @param (dict) testcase_template
       {
           "request": {
               "url": "http://127.0.0.1:5000/api/users/${uid}",
               "method": "POST",
               "headers": {
                   "Content-Type": "application/json",
                   "authorization": "${authorization}",
                   "random": "${random}"
               },
               "body": "${data}"
           },
           "response": {
               "status_code": "${expected_status}"
           }
       }
   @return (dict) parsed testcase with bind values
       {
           "request": {
               "url": "http://127.0.0.1:5000/api/users/1000",
               "method": "POST",
               "headers": {
                   "Content-Type": "application/json",
                   "authorization": "a83de0ff8d2e896dbd8efb81ba14e17d",
                   "random": "A2dEx"
               },
               "body": '{"name": "user", "password": "123456"}'
           },
           "response": {
               "status_code": 201
           }
       }
   """
   return self.substitute(testcase_template)

另外,如果算上单元测试用例的行数(731 行),总的Python代码行数能达到 1000 行的样子。嗯,代码可以精简,但是单元测试覆盖率还是要保证的,不达到 90% 以上的单元测试覆盖率,真不好意思说自己做了开源项目啊。

那这不足 300 行的 Python 代码,实际实现了哪些功能呢?

对比下《接口自动化测试的最佳工程实践(ApiTestEngine)》中规划的特性,已经实现了大半(前六项),至少已经算是一个有模有样的接口测试框架了。

  • 支持 API 接口的多种请求方法,包括 GET/POST/HEAD/PUT/DELETE 等
  • 测试用例与代码分离,测试用例维护方式简洁优雅,支持YAML/JSON
  • 测试用例描述方式具有表现力,可采用简洁的方式描述输入参数和预期输出结果
  • 接口测试用例具有可复用性,便于创建复杂测试场景
  • 测试执行方式简单灵活,支持单接口调用测试、批量接口调用测试、定时任务执行测试
  • 具有可扩展性,便于扩展实现 Web 平台化
  • 测试结果统计报告简洁清晰,附带详尽日志记录,包括接口请求耗时、请求响应数据等
  • 身兼多职,同时实现接口管理、接口自动化测试、接口性能测试(结合 Locust)

后面剩下的特性还在实现的过程中,但是可以预见得到,最后框架本身总的Python代码行数也不会超过 500 行。

当然,单纯地比代码行数的确是没有什么意义,写得爽写得开心才是最重要的。

最后引用下Guido van Rossum的语录:

Life is short, go Pythonic!

阅读更多

最后的最后

《ApiTestEngine 演进之路》系列文章还在继续写,只是前几天主要精力在编码实现上,博客方面没有同步更新,接下来我会整理好思路,继续完成余下的部分。

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

赞!

太好了,我这种超级小白都能看得懂 。简单修改了一下:1、把测试用例文件中的 config 提取出来,放到外部,用来切换不同的环境(test || online)2、测试用例加入级别 (p1 p2 or smoke),在 load 时可以设定跑全局还是冒烟 , 仅仅是为了满足我们目前工作的需求,减少测试用例的维护

tttttttttggggg 回复

求别黑😂
Java 之前其实也学过的,只是当前公司项目中 Java 后台的不多,而即使是用 Java 开发的,从通讯协议交互层面,Python 也都可以搞定,所以也就没有使用 Java 了。

大大我也推荐一下 java,现在很多后台框架用 java 写的,为方便测试我们是可以在现有框架基础上,自己在开发代码基础上,加一个测试接口类,优化效率。大大这么牛 B,等飞机的过程中就可以入门,下飞机就精通了。

卡斯 回复

对于其它的协议,就只有找开源的客户端了,之前我们有基于 XMPP 协议搞了一个 Python 客户端,来实现内部通讯工具的自动化测试

那就没法持续集成了

如果要考虑长期体系化、平台化的发展,还是 java 比较实在。
然后我非常推荐底层主体,支撑用 java 去实现,一些工具化的东西可以结合 python 非常实用~

卡斯 回复

我们选 java ,主要是因为大部分后端都用 java ,各种协议接入方便

无人值守回归测试怎么办

卡斯 回复

刚好我遇到一个要测微服务,sdk 方面的接口,有些加密的参数必须走 sdk。现在我手动运行 sdk 获取到参数后,然后复制到 python 测试接口框架,这样测试速度也挺快的。。。

debugtalk 回复

业务的特殊性 不同行业很难统一化 另外还有一个最大的问题就是 python 真的只适合 api 的,对于微服务或者其他协议的支撑力度还是弱了点,所以我们这边淘汰掉 python 版本的底层了

现在觉得,半自动化才好用。。手动改小代码,随着业务的变化而变化😎

卡斯 回复

@kasi @chenhengjie123 我的理解应该是都可以采用统一的模式的,后面我详细介绍下我使用的方式哈,到时候再 @ 你们帮忙看下

debugtalk 回复

你的是通用框架,属于基础型。卡斯的还包含了一些根据公司业务定制的部分,属于完整解决方案型。我觉得区别应该在这里。

debugtalk 回复

业务的一些特殊处理 流转的衔接逻辑,这些通用的都需要抽离出来,不体现在用例层面的

Nisir 回复

有空了可以细看下,能提些建议就更好了

#7 楼 @debugtalk 粗看了下 github 的代码,挺不错的,我会继续关注的。

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

卡斯 回复

业务流转不应该就是体现在用例里面么?例如生成一个订单号,然后去选仓、出库等操作,都可以通过一个用例场景来配置实现啊

debugtalk 回复

😂 我指的只是业务流转,并不涉及测试案例~

卡斯 回复

requests 主要是处理跟 HTTP 请求响应部分的;至于你说的那些业务逻辑,是单独实现的,后面你可以看下我的案例(还在写)。

debugtalk 回复

其实是业务不一样,我们这边需要实现各种业务,例如加密解密,数据库各种操作等等,日志的各种处理,流程的转向等等,甚至包括数据的生成逻辑,任务的调度,消息队列等等,还有预期判断 request 发送消息 uinittest 基本没用🙈

卡斯 回复

主要原因是我充分复用了 requests 库和 unittest 库的 API,包括后续性能测试实现那部分,会复用 Locust

代码估计很精炼啊,我看了下我们这边的 python 版本代码都不止那么点,应该几千行了

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