pytest文档73-pytest+yaml实现接口自动化框架之用例参数关联
Posted 上海-悠悠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了pytest文档73-pytest+yaml实现接口自动化框架之用例参数关联相关的知识,希望对你有一定的参考价值。
前言
使用 yaml 文件写测试用例的时候,如何在 yaml 文件的测试用例里面实现参数关联? 这是很多做自动化测试的小伙伴经常思考的一个问题。
接着前面的pytest+yaml 文件实现接口自动化框架,本篇使用环境变量的方式,让测试用例参数关联。
实现场景:上个接口返回的接口提取变量,在写个接口中引用变量
场景案例
我现在有一个登陆接口A,登陆成功后返回一个token值。有一个获取用户信息的接口B,但是接口B必须要先登录后传登录的token才能访问
A接口登录接口文档基本信息
- 访问地址:http://127.0.0.1:8000/api/v1/login/
- 请求类型:POST
- 请求头部:application/json
- 请求参数:{“username”:“test”, “password”:“123456”}
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/user/info/
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/user/info/ Authorization:"Token b7e02c959fbae4c2a0d9094f6f9b9a35fa8aaa1e" -v
GET /api/v1/user/info/ 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": "sucess!",
"code": 0,
"data": [{
"id": 15,
"name": "test",
"sex": "F",
"age": 20,
"mail": "1122@qq.com",
"create_time": "2020-12-18"
}]
}
传头部参数用xx:xxxx格式,中间用冒号:,如:User-Agent:demo-agent/1.0 'Cookie:a=b;b=c'
,由于Authorization参数中间有空格,用双引号包起来
conftest.py 代码实现
在 conftest.py 使用环境变量保存测试的结果提取的变量,使用 template 替换 yaml 文件的变量
import pytest
import requests
import jsonpath
import json
import yaml
from string import Template
import os
# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/
def pytest_collect_file(parent, path):
# 获取文件.yml 文件,匹配规则
if path.ext == ".yml" and path.basename.startswith("test"):
print(path)
print(parent)
return YamlFile(path, parent)
class YamlFile(pytest.File):
'''收集测试用例'''
def collect(self):
yml_raw = self.fspath.open(encoding='utf-8').read()
yml_var = Template(yml_raw).safe_substitute(os.environ)
yaml_data = yaml.safe_load(yml_var)
for yaml_case in yaml_data:
name = yaml_case.get("test").get("name")
values = yaml_case.get("test")
yield YamlTest(name, self, values)
class YamlTest(pytest.Item):
def __init__(self, name, parent, values):
super(YamlTest, self).__init__(name, parent)
self.name = name
self.values = values
self.s = requests.session()
def values_render_variable(self, values):
# values 是Test用例部分
yaml_test = Template(json.dumps(values)).safe_substitute(os.environ)
values = yaml.safe_load(yaml_test)
return values
def runtest(self):
# 运行用例
values = self.values_render_variable(self.values)
request_data = values.get("request")
print("\\n请求数据: ", request_data)
print(request_data)
response = self.s.request(**request_data)
print("接口返回", response.text)
# 判断是否有extract提取参数
if values.get("extract"):
for key, value in values.get("extract").items():
os.environ[key] = jsonpath.jsonpath(response.json(), value)[0]
self.assert_response(response, values.get("validate"))
def assert_response(self, response, validate):
'''设置断言'''
if validate:
for i in validate:
if "eq" in i.keys():
yaml_result = i.get("eq")[0]
actual_result = jsonpath.jsonpath(response.json(), yaml_result)
expect_result = i.get("eq")[1]
print("实际结果:%s" % actual_result[0])
print("期望结果:%s" % expect_result)
assert actual_result[0] == expect_result
YAML 文件案例
使用 extract 关键字提取变量,提取变量方式执行jsonpath表达式, 引用变量使用template 模板的引用语法$变量名
# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/
- test:
name: login case1
request:
url: http://49.235.X.X:7000/api/v1/login/
method: POST
headers:
Content-Type: application/json
User-Agent: python-requests/2.18.4
json:
username: test
password: 123456
extract:
token: $.token
validate:
- eq: [$.msg, login success!]
- eq: [$.code, 0]
- test:
name: get user info case1
request:
url: http://49.235.X.X:7000/api/v1/userinfo/
method: GET
headers:
Content-Type: application/json
User-Agent: python-requests/2.18.4
Authorization: Token $token
validate:
- eq: [$.code, 0]
- eq: ["$.data[0].name", test]
- eq: ["$.data[0].mail", 1122@qq.com]
执行结果
执行方式使用命令行运行,支持pytest的命令行指令
pytest
运行结果
>pytest -s
============================= test session starts ==============================
platform win32 -- Python 3.6.6, pytest-4.5.0, py-1.9.0, pluggy-0.13.1
rootdir: D:\\soft\\api_pytest_1208
collecting ... D:\\soft\\api_pytest_1208\\data\\test_info.yml
<Package D:\\soft\\api_pytest_1208\\data>
collected 2 items
data\\test_info.yml
请求数据: {'url': 'http://49.235.X.X:7000/api/v1/login/', 'method': 'POST',
'headers': {'Content-Type': 'application/json', 'User-Agent': 'python-requests/2.18.4'},
'json': {'username': 'test', 'password': 123456}}
{'url': 'http://49.235.X.X:7000/api/v1/login/', 'method': 'POST',
'headers': {'Content-Type': 'application/json', 'User-Agent': 'python-requests/2.18.4'},
'json': {'username': 'test', 'password': 123456}}
接口返回 {"code": 0, "msg": "login success!", "username": "test", "token": "09be4368534fa6320ed77a333e34c6661a36d40e"}
实际结果:login success!
期望结果:login success!
实际结果:0
期望结果:0
.
请求数据: {'url': 'http://49.235.X.X:7000/api/v1/userinfo/', 'method': 'GET',
'headers': {'Content-Type': 'application/json', 'User-Agent': 'python-requests/2.18.4',
'Authorization': 'Token 09be4368534fa6320ed77a333e34c6661a36d40e'}}
{'url': 'http://49.235.X.X:7000/api/v1/userinfo/', 'method': 'GET',
'headers': {'Content-Type': 'application/json', 'User-Agent': 'python-requests/2.18.4',
'Authorization': 'Token 09be4368534fa6320ed77a333e34c6661a36d40e'}}
接口返回 {"msg":"sucess!","code":0,"data":[{"id":15,"name":"test","sex":"F","age":20,"mail":"1122@qq.com","create_time":"2020-12-18"}]}
实际结果:0
期望结果:0
实际结果:test
期望结果:test
实际结果:1122@qq.com
期望结果:1122@qq.com
.
=========================== 2 passed in 0.49 seconds ===========================
以上是关于pytest文档73-pytest+yaml实现接口自动化框架之用例参数关联的主要内容,如果未能解决你的问题,请参考以下文章
pytest文档84 - 把收集的 yaml 文件转成pytest 模块和用例
pytest文档83 - 把收集的 yaml 文件转 Item 用例并运行
pytest文档72- 使用 template 替换 yaml 文件的变量
pytest + yaml 框架 -14.钉钉机器人通知测试结果