接口框架项目实战-pytest(五)yaml用例封装

yaml文件规则说明.txt

bash 复制代码
1、yaml 文件一级目录必须包括 name、request、extract、validate
2、在request一级目录下二级目录 必须包括 method、url
3、如果需要做接口关联的话,必须使用一级关键字:extract
get 请求 params 传参
post 请求
 json传参,通过json关键字
 表单传参 通过data关键字
 文件格式 通过files关键字
如 json提取
  extract:
      access_token: access_token
  正则表达提取
    extract:
      access_token: '"access_token":"(.*?)"'
当需要使用随机参数时 可以调用common_util.py 中get_random_value 方法
如
name: "ms${get_random_value(100,200)}"
     

common_util.py

bash 复制代码
import random


class CommonUtil:
    def get_random_value(self,min,max):
        return random.randint(int(min),int(max))

requests_util.py

bash 复制代码
import json
import re

import jsonpath as jsonpath
import requests

from pytestdemo.common.common_util import CommonUtil
from pytestdemo.common.yaml_util import read_config_file, read_extract_file, write_extract_file


class RequestsUtil:
    base_url=""
    def __init__(self,base,base_url):
        self.base_url=read_config_file(base,base_url)
    session=requests.Session()
    def replace_value(self,data):
        if data and isinstance(data,dict):
            str=json.dumps(data)
        else:
            str=data
        # 将变量替换成值
        for a in range(1,str.count("{{")+1):
            if "{{" in str and "}}" in str:
                print(str)
                start_index=str.index("{{")
                end_index = str.index("}}")
                print(start_index,end_index)
                old_value=str[start_index:end_index+2]
                new_value=read_extract_file(old_value[2:-2])
                str=str.replace(old_value,new_value)
        if data and isinstance(data,dict):
            data=json.loads(str)
        else:
            data=str
        return data
    def replace_load(self,data):
        if data and isinstance(data,dict):
            str_value=json.dumps(data)
        else:
            str_value=data
        # 将变量替换成值
        for a in range(1,str_value.count("${")+1):
            if "${" in str_value and "}" in str_value:
                start_index=str_value.index("${")
                end_index = str_value.index("}")
                old_value=str_value[start_index:end_index+1]
                fun_name=old_value[old_value.index("${")+2:old_value.index("(")]
                params=old_value[old_value.index("(")+1:old_value.index(")")]
                # 反射获取
                new_value=getattr(CommonUtil(),fun_name)(*params.split(","))
                str_value=str_value.replace(old_value,str(new_value))
        if data and isinstance(data,dict):
            data=json.loads(str_value)
        else:
            data=str_value
        return data
    def analysis_yml_send_reqeust(self,data):
        data_key=  dict(data).keys()
        print(data_key)
        if 'name' in data_key  and 'request' in data_key and 'validate' in data_key:
                # and 'extract' in data_key

            request_key=dict(data["request"]).keys()
            if 'method' in request_key and 'url' in request_key:
                headers=None
                method=data["request"]["method"]
                del data["request"]["method"]
                url=data["request"]["url"]
                del data["request"]["url"]
                if jsonpath.jsonpath(data,"$..headers") :
                    headers=data["request"]["headers"]
                    del data["request"]["headers"]
                files=None
                if jsonpath.jsonpath(data,"$..files"):
                    files=data["request"]["files"]
                    for key,value in dict(data["request"]["files"]).items():
                        files[key]=open(value,"rb")

                    del data["request"]["files"]
                print(data["request"])
                res = self.send_request(method=method
                                        , url=url
                                        , headers=headers
                                        ,files=files
                                        , **data["request"]
                                        )
                return_json=res.json()
                return_text=res.text
                print(res.text)
                if 'extract' in data_key:
                    for key,value in dict(data["extract"]).items():
                        # 正则表达式
                        extract_data=None
                        if "(.*?)" in value or "(.+?)" in value:
                           search_value=re.search(value,return_text)
                           if search_value:
                               extract_data=search_value.group(1)

                        else:
                            extract_data=return_json[value]
                        if search_value:
                            write_extract_file({key:extract_data})

            else:
                print("在request一级目录下二级目录 必须包括 method、url")
        else:
            print("1、yaml 文件一级目录必须包括 name、request、extract、validate")

    def send_request(self,method,url,headers=None,**kwargs):
        method=str(method).lower()
        url=self.base_url+self.replace_value(url)
        for key,value in kwargs.items():
            if key in ["params","data","json"]:
                kwargs[key]=self.replace_value(value)
                kwargs[key] = self.replace_load(value)

        res=RequestsUtil.session.request(method=method,url=url,headers=headers,**kwargs);
        return  res

yaml_util.py

bash 复制代码
import os

import yaml



def get_path():
    return os.path.abspath(os.getcwd().split("common")[0])
def read_config_file(one_node,two_node):
    with open(f'{get_path()}/common/config.yml',encoding="utf-8") as f:
        value=yaml.load(f,yaml.FullLoader)
        # print(value[one_node][two_node])
        return value[one_node][two_node]
def read_extract_file(node_name):
    with open(f'{get_path()}/common/extract.yml',encoding="utf-8") as f:
        value=yaml.load(f,yaml.FullLoader)
        return value[node_name]
def write_extract_file(data):
    with open(f'{get_path()}/common/extract.yml',encoding="utf-8",mode="a") as f:
        yaml.dump(data,f,allow_unicode=True)

def clean_extract_file():
    with open(f'{get_path()}/common/extract.yml',encoding="utf-8",mode="w") as f:
       f.truncate()
def read_testcase_yaml(file_path):
    print(f'{get_path()}{file_path}')
    with open(f'{get_path()}{file_path}',encoding="utf-8") as f:
        value = yaml.load(f, yaml.FullLoader)
        return value
if __name__ == '__main__':
    # print (read_config_file("base","base_php_url"))
    print(read_testcase_yaml("\\testcases\\get_token.yml"))

config.yml

bash 复制代码
base:
    base_php_url: http://47.107.116.139
    base_wx_url: https://api.weixin.qq.com

conftest.py

bash 复制代码
import pytest
from pytestdemo.common.yaml_util import clean_extract_file

@pytest.fixture(scope="session",autouse=True)
def clean_extract():
    clean_extract_file()

test_demo4.py

bash 复制代码
import random

import pytest

from pytestdemo.common.requests_util import RequestsUtil
from pytestdemo.common.yaml_util import write_extract_file, read_testcase_yaml


class Test4Api:
    access_token=""
    @pytest.mark.parametrize("data",read_testcase_yaml("/testcases/get_token.yml"))
    def test_get_token(self,data):
        RequestsUtil("base","base_wx_url").analysis_yml_send_reqeust(data)
    @pytest.mark.parametrize("data", read_testcase_yaml("/testcases/get_tags.yaml"))
    def test_get_tags(self,data):
        RequestsUtil("base", "base_wx_url").analysis_yml_send_reqeust(data)
    @pytest.mark.parametrize("data", read_testcase_yaml("/testcases/update_tag.yml"))
    def test_update_tag(self,data):
        RequestsUtil("base", "base_wx_url").analysis_yml_send_reqeust(data)
 
    @pytest.mark.parametrize("data", read_testcase_yaml("/testcases/uploadimg.yml"))
    def test_uploadimg(self,data):
        RequestsUtil("base", "base_wx_url").analysis_yml_send_reqeust(data)

get_token.yml

bash 复制代码
- name: 获取鉴权码
  request:
    method: get
    url: /cgi-bin/token
    params:
      grant_type: client_credential
      appid: xxx
      secret: xxx
  extract:
      access_token: '"access_token":"(.*?)"'
  validate:
      - eq:
          - status_code
          - 200

get_tags.yaml

bash 复制代码
- name: 获取标签
  request:
    method: get
    url: /cgi-bin/tags/get?access_token={{access_token}}
  validate:
      - eq:
          - status_code
          - 200

update_tag.yml

bash 复制代码
- name: 修改标签
  request:
    method: post
    url: /cgi-bin/tags/update?access_token={{access_token}}
    json:
      tag:
         id: 23475
         name: ms1213
         keyss: "{{access_token}}"
  validate:
      - eq:
          - status_code
          - 200

uploadimg.yml

bash 复制代码
- name: 修改标签
  request:
    method: post
    url: /cgi-bin/tags/update?access_token={{access_token}}
    json:
      tag:
         id: 23794
         name: "ms${get_random_value(100,200)}"
  validate:
      - eq:
          - status_code
          - 200

uploadimg.yml

bash 复制代码
- name: 修改标签
  request:
    method: post
    url: /cgi-bin/media/uploadimg?access_token={{access_token}}
    files:
      media: C:\\Users\\Administrator\\Desktop\\1.jpg
  validate:
      - eq:
          - status_code
          - 200

思考问题登录失败 之后的用例需要停止执行

相关推荐
是Dream呀11 分钟前
Python从0到100(七十八):神经网络--从0开始搭建全连接网络和CNN网络
网络·python·神经网络
程序猿000001号13 分钟前
Selenium 深度解析:自动化浏览器操作的利器
selenium·测试工具·自动化
菜狗woc16 分钟前
opencv-python的简单练习
人工智能·python·opencv
最爱番茄味29 分钟前
Python实例之函数基础打卡篇
开发语言·python
程序猿000001号1 小时前
探索Python的pytest库:简化单元测试的艺术
python·单元测试·pytest
engchina1 小时前
如何在 Python 中忽略烦人的警告?
开发语言·人工智能·python
Dream_Snowar2 小时前
速通Python 第四节——函数
开发语言·python·算法
西猫雷婶2 小时前
python学opencv|读取图像(十四)BGR图像和HSV图像通道拆分
开发语言·python·opencv
汪洪墩3 小时前
【Mars3d】设置backgroundImage、map.scene.skyBox、backgroundImage来回切换
开发语言·javascript·python·ecmascript·webgl·cesium
程序员shen1616114 小时前
抖音短视频saas矩阵源码系统开发所需掌握的技术
java·前端·数据库·python·算法