原文
一、背景
目前主流的H5页面动态获取内容的方式是采用ajax异步请求后台数据实现实时刷新,实际上就是用GET/POST的HTTP请求后台接口,再将返回的数据(一般是json或xml格式)渲染在页面上,因此保证H5页面接口的功能正确性就成为了页面内容数据正确的关键,普通的H5页面测试通常会采用手工测试的方式,这样只能模拟到正常的场景,对于异常的数据请求是无法覆盖的,并且对于请求参数很多的情况,效率很低,另外还有一部分数据内容接口是无页面的,如外部合作接口,只提供数据,对应的页面由合作方自己来做,则无法采用手工的方式进行测试。
实际上H5页面接口测试与传统的接口测试的基本思路是一致的,就是通过数据准备(包括正常和异常的参数)、接口调用、结果观察这三个流程来验证接口的功能逻辑符合预期,并且对于未预期的异常情况有较好的容错性和鲁棒性,只不过接口的调用参数形式有所不同,如下表所示。
另外在H5页面接口测试中还需要根据接口的实际情况模拟请求的HTTP头部,这些也是验证接口数据和逻辑的一部分,这些都是与传统的接口测试不同的部分。
文章接下来的部分就提供了一种能够完成H5页面接口测试的方法,主要应用于新开发的H5页面接口的功能测试。
二、为什么选择Unittest
通过第一部分的阐述,我们对H5页面接口测试的基本流程有了了解,那么为了实现H5页面测试,我们就需要一种工具,它需要有以下功能:
1、进行GET&POST请求调用
2、模拟HTTP头部进行请求
3、方便的构造参数
4、丰富的断言库,对结果进行判断
5、清晰的结果展示,SUCC /FAIL
6、方便的运行和调试,用例FAIL时给出调试信息
以上需求按照优先级排列,其中1和2是必须的,在之前的测试工作中用python来进行HTTP请求,原因是python的第三方库能够方便的模拟各种HTTP请求,并且调用非常简洁,因此很自然的想到了用python,同时为了能够对结果进行断言并且清晰的展示测试结果,我们采用了Unittest。
三、什么是Unittest
Unittest是python自带的单元测试模块,与java的单元测试框架junit类似,一个测试类中可以包含多个测试用例,每个用例以test_开头,执行前在setUp方法中进行初始化工作,执行后在tearDown方法中完成退出清理。多个测试类可以组成test suite同时进行测试。Unittest同样包含丰富的断言库,可以对结果类型、内容等多个方面进行验证,在结果展示方面,使用python IDE Pycharm能够得到清晰的结果以及错误信息,如下图所示。
在上面的测试结果中,能够清晰的看到用例总数、运行的用例数及失败的用例数,点击左边的用例名称,可以看到失败信息,还可以直接跳至对应的出错行,最左边的功能区的第二个按钮可以重跑所有失败用例。对于执行失败的用例,只要在对于用例区域右击,选择对应的”Debug…”选项就可以单独调试用例以确定是否是测试用例的问题导致执行失败,从而保证测试结果的准确性。
3.1 Unittest基本用法
下面是Unittest的基本使用方法,不同的测试用例可能稍有不同,但思路是一致的。
1) import Unittest
2) 定义一个继承自Unittest.TestCase的测试用例类:
3) 定义setUp和tearDown,在每个测试用例前后做一些辅助工作:
4) 定义测试用例,名字以test开头:
5) 编写用例,一个测试用例应该只测试一个方面,测试目的和测试内容应该很明确。进行了测试所需的操作后获取结果,然后调用assertEqual、assertRaises等断言方法判断程序执行结果和预期值是否相符,Unittest提供的结果断言主要有以下几个,后面的注释部分是各个断言的含义:
6) 调用Unittest.main()启动测试:
7) 观察测试结果,根据结果调整脚本或反馈问题。
四、需要怎么做
在开始编写测试用例之前需要确定接口的请求方式(GET/POST)、请求参数、请求所需的HTTP头部、返回的结果类型和内容基本要素等。其中请求参数又需要知道参数的类型、范围。根据这些信息能够组合出需要测试的场景,每一个场景就是一个测试用例,需要覆盖正常和异常的情况。一个基本的用例流程如下图:
下面将逐一介绍如何实现H5页面接口的功能测试。
4.1 请求参数设置
这个部分需要根据测试场景设置所需的请求参数,包括调用参数和HTTP头部(主要是referer、content-type、cookie等),对于调用参数的多种正常组合,可以使用单个参数循环遍历然后组合的方式,只需要一个测试用例即可,这样可以减少用例编写的工作量以及维护的成本。
4.2 接口调用
接口调用可以采用python的第三方库—Requests实现,Requests基于urllib,采用Apache2 Licensed开源协议的HTTP库,支持HTTP连接保持和连接池,支持使用cookie保持会话,支持文件上传,支持自动确定响应内容的编码,支持国际化的URL和POST数据自动编码。它比 urllib 更加方便,可以节约我们大量的工作,完全满足HTTP测试需求。使用Requests进行HTTP请求非常简单,下面分别是GET和POST基本请求。
GET:
Requests允许使用 params 关键字参数,以一个字典来提供这些参数。上面的代码将请求URL:http://httpbin.org/get?key2=value2&key1=value1。
POST:
对于POST请求,requests支持自动编码,只要将请求body传入json关键字参数即可,上面的代码将请求http://httpbin.org/post且请求body为:{“key1”: “value1”, “key2”:“value2”},如果请求body不是json格式,而是string格式,可以用data关键字参数直接设置。另外requests还会对参数自动进行URL编码。
如果需要为请求添加HTTP头部,只要简单地传递一个 dict 给头部参数即可:
上面的代码示例是POST请求,当然对于GET请求也是同样的。
对于请求得到的响应,requests也有丰富的方法处理,比较关键的几个方法:
上面代码执行后,code是响应的状态码,r_text是响应的内容,r_json是响应内容的json格式。
4.3 结果断言
得到了响应的状态和内容之后,就可以利用Unittest的断言库对结果进行校验了,首先需要校验的是响应的状态码,上面介绍了如何得到响应的状态码,直接与预期值进行判等,如:
其次是响应头,可能需要对Content-Type、Content-Length等关键字段进行验证,同样从响应中获取对应字段的值,然后直接用asserTrue断言去验证。
最后是响应的内容,HTTP接口的响应的内容一般来说有三种格式:json(最主要)、xml和html,对于json格式的响应可以直接用requests自带的json解析器进行解析,然后判断其中的关键key的值等,如下面的代码断言响应中的”success”是否为”True”;对于xml格式的响应,可以先获取响应的文本内容然后采用python的第三方类库如:lxml等,将xml文本转成标签树,然后通过对应的xpath读取值并进行校验;对于html格式的响应,获取响应的文本内容后用正则匹配或者xpath来得到需要校验的值。
五、总结
本文主要介绍了一种利用python第三方类库requests及单元测试工具Unittest实现H5页面接口功能测试的方法,主要运用场景是对于新开发的H5页面接口的功能测试,能够模拟到手工测试无法覆盖的异常场景并且有效降低测试工作量,并且能反复测试,快速验证问题。当然对于功能已经比较稳定的接口,需要其他的H5页面接口测试工具对接口进行监控及质量保证,多种方式结合才能更好的把控H5页面接口的质量。