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

yaml文件规则说明.txt

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

import random


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

requests_util.py

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

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

base:
    base_php_url: http://47.107.116.139
    base_wx_url: https://api.weixin.qq.com

conftest.py

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

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

- 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

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

update_tag.yml

- 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

- 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

- 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

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

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
pytestPython中最流行的测试框架之一,它支持使用yaml格式来编写测试用例。以下是使用pytestyaml编写测试用例的步骤: 1. 安装pytest和pyyaml: ```python pip install pytest pyyaml ``` 2. 创建一个yaml文件,文件名可以是任意的。在文件中,我们可以定义多个测试用例,每个测试用例包含以下信息: - name: 测试用例名称 - input: 测试用例输入 - expected_output: 测试用例预期输出 例如: ```yaml - name: addition_test input: a: 1 b: 2 expected_output: 3 - name: subtraction_test input: a: 5 b: 2 expected_output: 3 ``` 3. 在pytest测试文件中使用yaml文件中的测试用例。我们可以使用pyyaml库将yaml文件解析为Python对象,然后在pytest使用它。 ```python import yaml def test_yaml_cases(): with open('test_cases.yaml', 'r') as f: test_cases = yaml.load(f, Loader=yaml.FullLoader) for case in test_cases: input_data = case['input'] expected_output = case['expected_output'] assert your_function(*input_data.values()) == expected_output ``` 在上面的代码中,我们首先打开yaml文件并使用pyyaml库将其解析为Python对象。然后,我们迭代测试用例并执行测试。对于每个测试用例,我们使用字典的values()方法获取输入数据的值并将其作为参数传递给被测试的函数。最后,我们断言函数的实际输出与测试用例的预期输出相同。 4. 运行pytest测试框架来验证我们的测试用例是否可以正常工作。 ```python pytest test_yaml_cases.py ``` 通过上述步骤,我们可以快速有效地设计和执行测试用例使用pytestyaml编写测试用例不仅可以提高代码质量,还可以帮助开发人员减少繁琐的测试工作,从而更好地专注于软件开发。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值