httprunner 3.x学习4 - 测试用例参数关联(export)
前言
如何将上个接口的返回token,传给下个接口当做请求参数? 这是最常见的一个问题了。
解决这个问题其实很简单,我们只需取出token值,设置为一个中间变量a,下个接口传这个变量a就可以了。那么接下来就是解决两个问题:
- 如何取出token值?
- 如何参数关联?
环境: httprunner==3.1.4
场景案例
我现在有一个登陆接口A,登陆成功后返回一个token值。有一个获取绑定卡号的接口B,但是接口B必须要先登录后传登录的token才能访问
A接口登录接口文档基本信息
- 访问地址:http://127.0.0.1:8000/api/v1/login/
- 请求类型:POST
- 请求头部:application/json
- 请求参数:
B接口获取绑定卡号的接口文档基本信息
- 访问地址:http://127.0.0.1:8000/api/v1/userinfo/
- 请求类型:GET
- 请求头部:Content-Type: application/json
- 请求头部token参数: Authorization: Token xxxxx login token xxxxx
先不带token去访问接口B,使用命令行工具httpie测试接口
C:\Users\dell>http http://127.0.0.1:8000/api/v1/userinfo/
HTTP/1.1 401 Unauthorized
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 58
Content-Type: application/json
Date: Sat, 21 Sep 2019 14:06:15 GMT
Server: WSGIServer/0.2 CPython/3.6.0
Vary: Accept
WWW-Authenticate: Token
X-Frame-Options: SAMEORIGIN
{
"detail": "Authentication credentials were not provided."
}
不带token会提示没权限访问:401 Unauthorized
接口测试
先使用接口测试工具测试下,用postman,或者fiddler都可以,我这里为了查看报文信息方便,用httpie命令行工具
先访问接口A获取token值234af73571da46ade79ea6a74961b1d23d609b79
D:\>http http://127.0.0.1:8000/api/v1/login/ username=test password=123456 -v
POST /api/v1/login/ HTTP/1.1
Accept: application/json, */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 42
Content-Type: application/json
Host: 127.0.0.1:8000
User-Agent: HTTPie/1.0.3
{
"password": "123456",
"username": "test"
}
HTTP/1.1 200 OK
Allow: POST, OPTIONS
Content-Length: 109
Content-Type: application/json
Date: Sat, 21 Sep 2019 15:37:06 GMT
Server: WSGIServer/0.2 CPython/3.6.0
Vary: Accept, Cookie
X-Frame-Options: SAMEORIGIN
{
"code": 0,
"msg": "login success!",
"token": "234af73571da46ade79ea6a74961b1d23d609b79",
"username": "test"
}
传给下个接口B
D:\>http http://127.0.0.1:8000/api/v1/userinfo/ Authorization:"Token b7e02c959fbae4c2a0d9094f6f9b9a35fa8aaa1e" -v
GET /api/v1/userinfo/ HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Authorization: Token b7e02c959fbae4c2a0d9094f6f9b9a35fa8aaa1e
Connection: keep-alive
Host: 127.0.0.1:8000
User-Agent: HTTPie/1.0.3
HTTP/1.1 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 96
Content-Type: application/json
Date: Sat, 21 Sep 2019 16:04:25 GMT
Server: WSGIServer/0.2 CPython/3.6.0
Vary: Accept
X-Frame-Options: SAMEORIGIN
{
"msg":"success!",
"code":0,
"data":[
{
"id":105,
"name":"test",
"sex":"F",
"age":24,
"mail":"xxx@qq.com",
"create_time":"2020-06-12"
}]
}
传头部参数用xx:xxxx格式,中间用冒号:,如:User-Agent:demo-agent/1.0 'Cookie:a=b;b=c'
,由于Authorization参数中间有空格,用双引号包起来
yml 格式参数关联
提取登录接口返回的 token 值,使用 extract 提取器
extract:
token: content.token # 提取token
在 config 中使用 export 关键字导出变量,设置为全局变量,方便后面的步骤调用
config:
name: logincase
variables: {}
export:
- token
下个接口的用例引用token参数使用$token
,完整的用例userinfo.yml如下
# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/
config:
name: logincase
base_url: http://127.0.0.1:8000
variables: {}
export:
- token
teststeps:
-
name: step1 login
request:
url: /api/v1/login/
method: POST
headers:
Content-Type: application/json
User-Agent: python-requests/2.18.4
json:
username: test
password: 123456
extract:
token: content.token # 提取token
validate:
- eq: [status_code, 200]
- eq: [headers.Content-Type, application/json]
- eq: [content.msg, login success!]
- eq: [content.code, 0]
-
name: step2 get user info
request:
url: /api/v1/userinfo/
method: GET
headers:
Content-Type: application/json
User-Agent: python-requests/2.18.4
Authorization: Token $token # 引用token
validate:
- eq: [status_code, 200]
- eq: [headers.Content-Type, application/json]
- eq: [content.code, 0]
- eq: [content.data.0.mail, 283340479@qq.com]
pytest 用例结构
config 中 export 导出,主要是为了关联做准备。导出的变量,主要是用于Step之间参数的传递。
如果导出多个变量,格式如下:
.export(*["token", "var1", "var2"]
userinfo_test.py 对应的代码如下
# NOTE: Generated By HttpRunner v3.1.4
# FROM: userinfo.yml
# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
class TestCaseUserinfo(HttpRunner):
config = Config("logincase").base_url("http://127.0.0.1:8000").export(*["token"])
teststeps = [
Step(
RunRequest("step1 login")
.post("/api/v1/login/")
.with_headers(
**{
"Content-Type": "application/json",
"User-Agent": "python-requests/2.18.4",
}
)
.with_json({"username": "test", "password": 123456})
.extract()
.with_jmespath("body.token", "token")
.validate()
.assert_equal("status_code", 200)
.assert_equal('headers."Content-Type"', "application/json")
.assert_equal("body.msg", "login success!")
.assert_equal("body.code", 0)
),
Step(
RunRequest("step2 get user info")
.get("/api/v1/userinfo/")
.with_headers(
**{
"Content-Type": "application/json",
"User-Agent": "python-requests/2.18.4",
"Authorization": "Token $token",
}
)
.validate()
.assert_equal("status_code", 200)
.assert_equal('headers."Content-Type"', "application/json")
.assert_equal("body.code", 0)
.assert_equal("body.data[0].mail", "283340479@qq.com")
),
]
if __name__ == "__main__":
TestCaseUserinfo().test_start()
网易云课程地址