python自动化框架pytest接口关联串联_pytest文档73-pytest+yaml实现接口自动化框架之用例参数关联...

前言

使用 yaml 文件写测试用例的时候,如何在 yaml 文件的测试用例里面实现参数关联? 这是很多做自动化测试的小伙伴经常思考的一个问题。

接着前面的pytest+yaml 文件实现接口自动化框架,本篇使用环境变量的方式,让测试用例参数关联。

实现场景:上个接口返回的接口提取变量,在写个接口中引用变量

场景案例

我现在有一个登陆接口A,登陆成功后返回一个token值。有一个获取用户信息的接口B,但是接口B必须要先登录后传登录的token才能访问

A接口登录接口文档基本信息

请求类型:POST

请求头部:application/json

请求参数:{"username":"test", "password":"123456"}

B接口获取绑定卡号的接口文档基本信息

请求类型: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": "[email protected]",

"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", [email protected]]

执行结果

执行方式使用命令行运行,支持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

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":"[email protected]","create_time":"2020-12-18"}]}

实际结果:0

期望结果:0

实际结果:test

期望结果:test

实际结果:[email protected]

期望结果:[email protected]

.

=========================== 2 passed in 0.49 seconds ===========================

你可能感兴趣的:(python自动化框架pytest接口关联串联_pytest文档73-pytest+yaml实现接口自动化框架之用例参数关联...)