Api 自动化测试
源码:https://github.com/wupeng-pay...
一、Config 模块
|-- config.ini
|-- product-config.ini
|-- test-config.ini
在 config.ini 中的 [ENVIRONMENT]
块中定义环境、发件人、收件人、邮件主题,如:
[ENVIRONMENT]
environment=test
[SENDER]
smtpserver = mail.myhexin.com
user = [email protected]
password = xxxxxx
sender = [email protected]
[RECEIVER]
;receiver = [email protected], [email protected]
receiver = [email protected]
[MSG]
subject = 小象自动定时测试报告(生产api)
将会读取 test-config.ini 文件中的配置,由这种方式将配置文件与环境剥离开。
[HOST]
cn_https=https://xxx.10jqka.com.cn
cn_http=http://xxx.10jqka.com.cn
en_https=https://
en_http=http://
在 [HOST]
块中定义host,可以在 case.json 文件中使用,如:
{
"request": {
"host": "{{cn_https}}",
"api": "/info/api/v3/auth/post/login",
"method": "POST",
"header": {
"Content-Type": "application/x-www-form-urlencoded"
}
},
....
}
使用 {{}}
包裹,将会从config中解析。否则,当成字符串处理
二、case 定义形式
测试用例,以 json 文件的形式定义。主要包括一个 request 块,和多个 case 块。基本的形式如下:
{
"request": {
"host": "{{cn_https}}",
"api": "/info/api/v3/auth/post/login",
"method": "POST",
"header": {
"Content-Type": "application/x-www-form-urlencoded"
}
},
"case_01": {
"query":"test=1&test2=2",
"data": [
{
"key": "useragent",
"value": "android/1.5.3",
"type": "text"
}
],
"assert": [
{
"type": "eq",
"rules": "status",
"expect": 0,
"msg": "这里是报错显示的msg"
}
],
"set_result": [
{
"key": "cache_key",
"value": "payload.id"
}
]
}
}
request
对象中包含:
- host:在config 中定义
- api:接口地址,与host组成完整url
- method:请求方式,支持POST与GET
- header:对象,可填写多个键值对
case_01
为用例名称,一个json文件中可以含有多个用例。同一个文件下所有的用例,请求的内容都相同。
- query: 字符串,按照"field1=value1&field2=value2"规则,解析结果将于data合并
-
data: 数组,按照method内容,post则放在body中发送,get则放在url中。数组中可放入多个对象。
- key: 必填,参数名称。
- value:必填,请求内容。
- type:必填,类型:text/array/json/file
- file_name: 非必填,type 为 file 时需要参数。文件名称。
- file_type: 非必填,type 为 file 时需要参数。文件类型。例子:text/plain
- from:非必填,数据来源。当数据来源于cache时,填cache。目前只支持cache
-
assert:数组,定义请求结果断言。可以含有多个对象,定义不同的断言,
- type:断言类型,eq/not_eq等
- rules:取值规则,返回数据中的结构 例如 payload.group_id
- expect: 预期值,对比用
-
set_result:非必填 数组,需要保存在cache中的数据
- key: 名称,注意唯一性
- result_field:返回数据的结构 例如:payload.group_id
三、定义单元测试
# -*- coding: utf-8 -*-
import unittest
from Common.BaseTest import BaseTest
# 定义测试类
class TestLogin(BaseTest):
# 定义测试用例文件地址
json_file = "/TestData"
# 定义单个测试用例
def test_01_login(self):
# 定义需要执行的case名称
self.run_case("case_01")
def test_02_login(self):
self.run_case("case_02")
# 保存全部返回结果
self.set_result("943189180")
def test_03_create_group(self):
# 在用例中定义测试用例文件地址
self.set_json_file("/TestData")
# 定义单个参数
self.set_single_extra_body("code_list", "1050992,1050991")
self.set_single_extra_body("code", "1050991")
self.run_case("case_01")
if __name__ == '__main__':
unittest.main()
四、Cache 模块
为了方便用例间上下文联动,引入cache模块。可以将接口返回的结果保存在cache中,也可以从cache中取出所需要的内容放入到请求体中。
但需要注意的是,cache模块受用例执行顺序的影响,必须保证当前取值的用例在存值用例的后面执行。
使用:
-
配合 json 文件:
-
存值,在 {case_name}.set_result 块中定义需要保存的数据
例如:
{ "set_result": [ { "key": "943189180_token", "result_field": "payload.token" }, { "key": "943189180_all", "result_field": "*" } ] }
-
取值,在 {case_name}.data 块中定义需要取值的数据
例如:
-
{
"data": [
{
"key": "token",
"value": "{{943189180_token}}",
"type": "text"
}
]
}
```
data 中使用 `{{}}` 将会从cache中取值
-
配合 test 类:
-
存值:
使用 set_result 方法保存全部数据。
self.run_case("case_02") self.set_result("943189180")
这两个方法会将
case_02
的所有返回结果保存在943189180
键中。set_result 方法 必须在 run_case 之后执行。也可以写成:
self.run_case("case_02").set_result("943189180")
-
取值:
使用 get_result 方法从cache中取值。
self.get_cache(key="943189180",r="")
其中,r 为取值规则。如果为空,则将
943189180
键中所有数据取出,如果需要取出指定结构下的数据,只需要给r
设定规则,例如:self.get_cache(key="943189180",r="payload.token")
-
五、给case请求体增加参数
-
增加 header
-
set_extra_header
self.set_extra_header({"test_header":"header","test_data2":"header"})
-
set_single_extra_header
self.set_single_extra_header(key="test_header",value="header")
-
-
增加 body(post):
将在body体中传输
-
set_extra_body
self.set_extra_body({"test_data":"data","test_data1":"data"})
-
set_single_extra_body
self.set_single_body(key="test_data",value="1")
-
-
增加 params (get):
将在url中传输
-
set_extra_params
self.set_extra_body({"test_data":"data","test_data1":"data"})
-
set_single_extra_params
self.set_single_body(key="test_data",value="1")
以上将被解析为: http://www.domian.com/some_ap...
-
六、执行顺序问题
在 run_all_case.py
文件中定义测试用例执行:
suite = unittest.TestSuite()
suite.addTest(TestVanishLogin('test_1_login_01'))
suite.addTest(TestVanishLogin('test_1_login_02'))
suite.addTest(TestVanishLogin('test_2_create_01'))
runner = unittest.TextTestRunner(verbosity=2)
runner.run(suite)
使用 addTest 手动增加测试用例,设置执行顺序。在执行用例很多的情况下,比较麻烦,也可以使用:
discover = unittest.defaultTestLoader.discover(test_dir, pattern='test_*.py')
#runner.run(discover)
runner = HTMLTestRunner(stream=fp, title=u'测试报告', description=u'用例执行情况:')
runner.run(discover)
使用自动 discover 功能,自动加载所有测试用例,但其加载执行的顺序是按照文件名和方法名排序的。
需要优先执行的文件可以将文件名命名为: test_1_1_1_vanish_account_login.py
文件内需要优先执行的用例可以将方法名命名为: test_1_1_account_login_01()
用名称中的数字用来控制用例执行顺序。