《移动App测试实战》——2.1 轻量接口自动化测试-阿里云开发者社区

开发者社区> 华章出版社> 正文

《移动App测试实战》——2.1 轻量接口自动化测试

简介:

本节书摘来自华章出版社《移动App测试实战》一 书中的第2章,第2.1节,作者:邱鹏 陈吉 潘晓明,更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.1 轻量接口自动化测试

无论Web互联网的产品还是移动互联网的产品都必须依赖大量的后台接口提供的服务,有很多的业务逻辑都是放在后台来处理的,所以非常有必要对这部分逻辑来做测试验证。技术方案上,也可以模拟用户的UI操作,从界面上发起相关的请求。但是实际中,会发现这样的做法效率不高而且稳定性不够,开发和维护的代价也比较大。针对这部分的测试,最直接的方式还是从接口层面发起请求来验证。
就目前观察,对于一些比较稳定的基础性组件,比如底层平台、API、SDK等,或者功能通用性高的产品,比如防火墙、邮件系统等,都可以做到比较高的自动化率,而且自动化测试开发的方案也相对比较明确。相比而言,偏重应用层业务的测试团队,通常在自动化方面的开展要困难很多,主要有以下几个问题:
首要的问题是版本的节奏,互联网产品版本节奏非常快,一个稍大的系统一周发布上百个功能特性是一件很常见的事情。团队成员有非常多的精力消耗在这些功能版本上,需要快速理解业务,构建测试环境,进行bug验证回归,以及发布和线上验证等,留给业务测试人员构建自动化用例的时间非常少。
自动化框架的开发代价比较大。自己开发或者维护过测试框架的人可能都深有体会,这绝不是一件容易的事情,其工作量和持续的时间往往会超出我们的预期,特别是对于大部分的互联网测试团队,尤其是一些初创团队。而另一方面,也很难找到一个现成的,能满足特定需求的平台。
实际的项目,特别是大型的项目,功能通常都非常的复杂,需要将业务逻辑通过框架的能力来表达,对构建用例来说也存在一定的门槛。而测试开发人员由于对各个业务细节的了解程度不够且精力有限,对于需要构建大规模自动化测试用例的系统也是一个挑战。
对于一些大的互联网研发团队,如果有一个比较大的测试部门,对应有比较强的测试开发能力,可以考虑自己开发一套自动化测试框架,然后可以在多个业务测试团队复用。对于一些人力有限的团队,则需要考虑一些轻量级的方式。这里不准备介绍如何开发一个自动化框架,那可能需要写一本书的篇幅。下面将要介绍的是适合小团队的一些测试自动化的方法,基于我们之前在一些实际项目中的实践。这套方法我们曾在几个不同类型的项目中得到应用,包括电商的后端ERP系统、Web网站以及App的后台接口,都获得了比较好的实际效果,同时测试开发和用例编写的代价相对可以承受。

2.1.1 JMeter关于自动化方面的特性介绍

这个轻量级方法的核心是采用开源测试工具JMeter作为引擎,把发送接口请求,以及结果的解析和断言的工作都交给JMeter的基础功能来实现。这样的考虑涉及两个问题:一是为什么不从头开发一套完整的自动化框架?二是为什么采用JMeter?
关于不从头开发一套完整的框架,主要的考虑如下:
1)首先主要是开发成本的考虑。用当前任何一个主流的开发语言,比如Java/Python/PHP等,写一个协议层面的收发都非常简单,因为有了大量的通用的库。但是如果用于自动化测试,需要考虑的方面非常多,比如以HTTP协议为例:
需要考虑数据编码的问题
需要处理连接的建立,销毁的问题
需要考虑Cookie的问题,自动重定向的问题,是否用keep-alive
对于POST,需要处理发送前的数据准备问题
需要处理代理的问题
需要处理返回数据的解析
需要支持各种断言的形式
2)在自动化测试的开展过程中,会不断对底层框架提出新的要求,需要有持续的测试开发人力投入。
3)需要保证框架的高质量和稳定性。很多内部开发的框架都会遇到上面的问题,投入了大量人力,开发了很长时间,也需要持续的维护,但是一旦有大的产品和人员的变动,很多时候,框架或者框架的很多功能都会被废弃。
4)这可能不是团队的工作核心。开发一个HTTP等基础协议的收发处理的框架对很多业务测试团队来说,都不是核心的职责和最重要的事情,特别是人力有限的情况下。
基于这样的考虑,为了快速构建一套可用的自动化框架,我们决定寻找一个开源的工具,能完成协议层面的基本功能。最后我们选用了JMeter,基于它来构建我们的自动化平台。
JMeter是Apache Software Foundation下面的一个开源项目,有超过10年的历史了。它是一个纯Java编写的测试工具,最早主要用于HTTP协议性能测试(现在这仍是其主要用途之一),但是后来随着功能的逐渐丰富完善,它也成为一个接口协议测试工具,以及自动化测试工具。下面介绍下它的一些特点,主要从功能测试的角度,其他更进一步的信息可以参考它的官方文档,或者下载之后试验。

  1. 支持多种不同类型的协议
    从图2-1可以看出,JMeter自带支持的接口协议有多种,可以直接应用,省去了上面提到的接口协议的数据收发方面的开发。
  2. 对HTTP协议的支持比较全面
    HTTP是互联网最常用的协议,目前很多移动互联网产品也是通过HTTP协议来完成后台的交互。JMeter对HTTP的支持比较全面,如图2-2所示,对于协议方法、请求的参数和选项、代理等方面都提供了支持。

1410e23e5e7bd12c7cec171f6d54de504759328d

除此之外,还提供了Cookie管理、Cache管理、消息头和授权管理等辅助功能,如图2-3所示。

f0fe0d5d3f824c00739949a2699b7d52d628941a

3.其他非直接支持的协议可以通过扩展方式实现
某些实际项目中,可能在App和服务端通信上采用非上述标准协议之外的其他协议,包括一些私有协议。对于这种情况,可以通过JMeter提供的通用组件来编写代码扩展,或者更进一步编写JMeter插件,类似于一个新的Sampler。接下来我们通过一个例子看看如何通过现有组件来扩展。
对于其他私有通信协议的接口,我们可以通过JMeter的OS Process Sampler来进行桥接和测试,如图2-4所示。OS Process Sampler可以用来启动一个可执行程序,由于是通过命令行方式启动,所以我们可以用任何语言编写一个测试用的可执行程序。在该可执行程序中调用我们的接口,调用完成后可以做简单的解析判断输出文本信息,也可以把返回的原始数据输出而交由JMeter做后续解析判断。具体做法是往该进程的标准输出流写入数据。之后在JMeter 中即可读取这些数据。
以C#语言为例,在测试程序中我们可以用下列代码输出文本到标准输出流:

Console.WriteLine("[!Error!]");```
在JMeter中我们可以使用BeanShell PostProcessor来处理可执行文件输出,如图2-5所示。
使用BeanShell PostProcessor来处理可执行文件输出,BeanShell PostProcessor中获取输出的关键代码如下:

var res=prev.getResponseDataAsString();
var hasErr=res.contains("[!Error!]");
if(hasErr)
{
//这里可以增加断言或者进行变量赋值等常用操作
}`

3ff79e54e2d275d054ca49416c1b55cf7f85ae5c

通过上述例子可以看到,测试用可执行文件的输出与JMeter的输入数据需要有一定的约定格式。该数据格式在项目中可以根据实际情况自由设计。

  1. 支持丰富的断言
    对于接口测试而言,断言是一个非常重要的功能,而且实际项目中,可能需要比较复杂的断言方式来判断结果是否正确。

图2-6所示是JMeter提供的响应断言,可以看出,其支持的检查内容比较多,包括响应代码、响应头和Body内容等方面,检查方式也支持多种不同的规则。

  1. 支持内嵌自定义脚本
    实际中,一个功能的自动化可能需要多个步骤,包含调用多个接口来完成。而多个接口之间有一些逻辑管理,比如后面的接口依赖前面接口的响应数据,甚至数据需要做一些处理才能为后面的接口所用。针对这种情况,可以通过JMeter内嵌支持的自定义脚本来实现,可以使用JavaScript和Java等语言。

0697fa22fd3a7bb622d4b4705c8486836d126e33

下面我们以JavaScript语言为例,通过一个实际的例子来看看,如图2-7所示。

14f576d7120ae9454107a95b52993f574b80cd14

这个例子是针对一个电商App的首页楼层布局的检查,前面的接口返回了各个楼层的信息,这里的BSF PostProcessor里面的JS脚本以前面接口的返回作为参数,解析出其中各个楼层的信息,然后存入到数组中。之后后续的接口就可以读取这些变量,逐个地访问这些楼层的信息。

  1. 可以直连DB检查数据
    在实际的接口自动化中,除了通过接口层面来检查执行结果,有些不能在接口中返回的,或者接口中信息比较少的,也可以通过直接查询DB的方式来检查数据和结果。在JMeter中可以通过JDBC Request这个Sampler来实现。图2-8所示是一个具体的例子。

4c91b8c85f81ac6880612e9aaf73a5a8d0549217

可以直接在其中编写SQL脚本来访问对应DB中的数据,获取到数据后可以存入变量做进一步的断言和处理。

  1. 可以嵌入执行第三方命令行
    可以使用OS Process Sampler和BeanShell Sampler来执行一些外部的命令、用户环境和数据的准备等功能。
  2. 文本的输入和输出
    JMeter的输入和输出都是文本的形式,包括界面编辑的配置存成jmx文本,需要的测试数据也可以通过文本的方式提供,另外,执行之后的结果也是存成文本的。这样的方式,方便了后续其他脚本的处理和结果的解析。
  3. 图形界面和命令行启动执行
    JMeter本身提供图形界面,极大地方便了用例制作和调试,不但提供请求配置和脚本编写的界面,也可以用于执行和调试,并有对应的多种形式的报告,让用例制作和调试的过程变得简单。当调试完成后,可以用命令行的方式来执行JMeter脚本,而不需要打开GUI,也方便自动化框架的封装。
  4. 工具本身非常稳定
    最后一点也是一个很重要的方面,因为自动化会比较频繁的执行,而且可能执行的时间比较长,所以工具和框架本身的稳定性也非常重要。JMeter作为一个开源工具,有非常广泛的用户基础,得到过比较充分的验证。新版本也在持续开发中,所以稳定性和可维护性方面比较有保障。

还有更多细节的功能这里不一一介绍了,有了上述这些特性后,就可以用于接口自动化的构建了。如果独自开发上面提到的这些功能,并在实际使用中稳定下来需要花费比较大的代价。借助已有的开源工作,围绕其做二次开发,是下面的自动化方案可以做到比较轻量级的主要原因。

2.1.2 基于JMeter的轻量接口自动化实践

有了上面这些基本的功能,接下来需要考虑如何整合成一套完整的方案,包括考虑用例的可复用和可扩展。
实践中我们的基本思路如下:

  1. 用例的分层
    为了更好的复用和管理,我们对用例的层次进行一些划分,并给出名称的定义。单次接口请求是一个最小粒度的操作,比如下面示例中的一次HTTP请求,在以下我们称之为CGI。CGI这个词的本意是通用网关接口,由于习惯的原因,常常用来代称单个业务接口。Function是一个对外有逻辑意义的请求组合,比如提交订单、审核订单。TestCase是一个成品,TestSuite是一个用例的集合。基本的组织方式如图2-9所示。

通过这样的分层,整体逻辑就比较清楚了,CGI对于一个具体的接口是最小粒度的元素,如果接口变化了,只需要修改对应的CGI用例。Function层面是一个有逻辑意义的功能,可能需要多个CGI共同完成,相当于做了一层封装,为后面构建用例打下基础。

16992cad3383f4341dd86cd95f42ac51b5550fe3

每个子系统的目录结构如图2-10所示。

cde0bdec3fe287f20ec2d89e8616be652848f1fc

这里有个需要注意的小地方,为了部署的时候更灵活,希望脚本中互相引用的文件是相对的路径,但是JMeter支持不太好,默认的根目录是bin,所以简单的做法是把整个自动化用例的目录复制到JMeter的bin下面。
2.完整的自动化用例结构
因为我们有多个系统,对应多个测试小组,大家各有专注,而整个业务又是一个长链条。Function层就是我们复用的基础,里面包含了对CGI层接口的调用。注意一点,JMeter 2.10开始建议用TestFragment来组织,而TestFragment是不能直接执行的,只是些积木,到了TestCase层面再用ThreadGroup线程组才可以执行。图2-11是一个Test Fragment的示例。

3ef473ab115cbcd63c8ec7d2682516d1896e2d25

图2-12所示是一个完整的TestCase,包含了本系统和其他系统的一些Function步骤。
实际多人协作的过程汇总,用例细节有很多需要规范的地方,比如命名规范,这样便于多人协作。

  1. 数据的输出
    JMeter里面配置和编写用例执行完了之后,需要拿到输出的结果,外层的自动化框架才能进行解析和结果的输出。这里我们通过添加一个“察看结果树”的监听器,将所有的执行结果输出到一个文本文件里面,如图2-13所示。为了解析方便,通过变量指定了一个确定的文件名,数据结果方面选择了所有的列,便于得到完整的结果并处理。

fca0037dc9d2848797a16aa446c57d9ca6423054
  1. 自动化的报告
    基于上述步骤输出的文本结果,可以编写一个解析器,把结果解析成比较易于阅读的方式。然后生成对应的报告,每次执行完成之后自动地发邮件报告出来。图2-14是一个自动化测试报告的例子。

a9a177dc604fcffae7195e9012c699138e0c547a
  1. 用例执行细节查询
    除了上面汇总之后的结果报告,还需要一个地方能看到用例执行的细节,帮助定位问题。实际中我们构建了一个Web平台,测试人员可以在上面看到每次测试的结果,以及每个用例的执行细节。

为了更好地定位问题,需要把每个接口执行的细节也暴露出来,点击详情可以看到调用的情况,包括request和response的数据,如图2-15所示。
到这里为止,一个比较完整的可以在实际项目中应用的自动化框架就完成了。在实际的运作过程中,可以对业务测试人员进行一些JMeter方面的培训,让大家熟悉如何构造接口的请求,以及断言处理等模块,然后就可以编写对应的用例了。当然,如果多个人来准备测试用例,也需要知道哪些CGI和Function级别的封装是已有的,可以复用。

e4519cb5135bb1801dbf382fa883e2a273622cd8

可见,除了JMeter以外的框架部分的开发工作外,工作量不是很大,很多较小规模的测试团队也可以承受。综合来看,基于这样的方案可以快速地把一个可用的自动化系统构建起来。
上述方案在一个项目中实践的情况如下:
1)覆盖了4个大的系统,200多个CGI接口,以及100多个功能点。每个系统在构建后快速地通过以上自动化用例来进行回归,并发出邮件报告,框架整体比较稳定。
2)整个过程,不算制作用例的时间,我们实际投入的测试开发的人力约为一个人/月。
3)大部分业务测试人员都参与到了用例的制作,提升了对业务逻辑的理解,并且对部分人员来说,也学习了HTTP协议等基础知识,并编写了少量的脚本,提升了业务测试人员的自动化和测试开发能力。
总体来说,达到了轻量化来构建接口自动化的目标。
除了以上好处,也有一些不方便的地方需要指出:
JMeter在包含其他的jmx脚本后,不能直接在界面显示加载的内容,所以看不到被包含的脚本里面的步骤,调试的时候不方便。不过JMeter可以支持多个实例同时运行,所以在编写和调试阶段,可以同时打开多个JMeter窗口,一定程度上可以缓解这个问题。
最后的测试报告里面,不能控制显示结果的层次,是直接展开成每个接口的结果,当用例的步骤过多时查看起来不是特别方便。
除了技术层面的考虑,自动化执行的过程中还有几个建议值得考虑:
1)一定要强挂钩到测试和发布的环节。这一点看起来没那么重要,但是如果不希望自动化测试成为花瓶,必须要这样做。互联网产品的节奏非常快,如果自动化不能实际地在项目中发挥效果,就很容易被荒废。目前来看最合适的点是在每次自动部署后快速地把自动化用例执行一遍,这要在手工测试开始之前。这也是持续集成的思路,可以快速地发挥自动化的价值。
2)报告也需要自动化地发出来,并且邮件抄送给相关的开发人员、测试人员和团队负责人。这样可以让大家快速地关注到结果。
3)非100%成功的都要跟进。宁愿少而精,就像“破窗理论”指出的,如果能容忍一个用例失败,就会有2个、3个,也会让自动化慢慢失去意义。我们的做法是只要有失败,对应系统的测试负责人员需要进行定位并邮件回复出问题原因和处理措施。
4)需要关注用例的细节。测试团队的负责人需要去关注用例的质量,而不只是用例的数量和执行情况,比如断言做到什么程度,哪些自动化数据是写死的,哪些参数化了,功能之间的复用情况,这些都是影响整个自动化的稳定性和可维护性的具体方面。

版权声明:如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:developerteam@list.alibaba-inc.com 进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:

华章出版社

官方博客
官网链接