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 ===========================

2021年第六期《python接口自动化+测试开发》课程,1月9号开学(火热报名中!)
本期上课时间:1月9号-4月18号,每周六、周日晚上20:30-22:30

(0)

相关推荐

  • Python Requests Pytest YAML Allure实现接口自动化

    作者:wintest 链接:https://www.cnblogs.com/wintest/p/13423231.html 本项目实现接口自动化的技术选型:Python+Requests+Pytest ...

  • pytest文档71-pytest+yaml实现接口自动化框架

    前言 httprunner 用 yaml 文件实现接口自动化框架很好用,最近在看 pytest 框架,于是参考 httprunner的用例格式,写了一个差不多的 pytest 版的简易框架 项目结构设 ...

  • pytest文档67-在 pytest.mark.parametrize 中使用 fixture

    前言 测试用例参数化的时候,使用 pytest.mark.parametrize 参数化传测试数据,如果我们想引用前面 不同fixture 返回的数据当测试用例的入参,目前没好的解决办法. 可以用fi ...

  • pytest文档72- 使用 template 替换 yaml 文件的变量

    前言 在接口自动化测试的时候,yaml 文件一般放测试的数据或当配置文件使用,yaml 文件存放静态的数据是没问题的,python的数据类型基本上都是支持的. 有时候我们想在 yaml 文件中引用变量 ...

  • pytest文档1-环境准备与入门

    前言 首先说下为什么要学pytest,在此之前相信大家已经掌握了python里面的unittest单元测试框架,那再学一个框架肯定是需要学习时间成本的. 刚开始我的内心是拒绝的,我想我用unittes ...

  • pytest文档2-用例运行规则

    用例设计原则 文件名以test_*.py文件和*_test.py 以test_开头的函数 以Test开头的类 以test_开头的方法 所有的包pakege必须要有__init__.py文件 help帮 ...

  • pytest文档3-pycharm运行pytest

    前言 上一篇pytest文档2-用例运行规则已经介绍了如何在cmd执行pytest用例,平常我们写代码在pycharm比较多 写完用例之后,需要调试看看,是不是能正常运行,如果每次跑去cmd执行,太麻 ...

  • pytest文档5-fixture之conftest.py

    前言 前面一篇讲到用例加setup和teardown可以实现在测试用例之前或之后加入一些操作,但这种是整个脚本全局生效的,如果我想实现以下场景: 用例1需要先登录,用例2不需要登录,用例3需要先登录. ...

  • pytest文档6-fixture之yield实现teardown

    前言 上一篇讲到fixture通过scope参数控制setup级别,既然有setup作为用例之前前的操作,用例执行完之后那肯定也有teardown操作. 这里用到fixture的teardown操作并 ...

  • pytest文档7-生成html报告

    前言 pytest-HTML是一个插件,pytest用于生成测试结果的HTML报告.兼容Python 2.7,3.6 pytest-html 1.github上源码地址[https://github. ...