pytest封装请求类

一、解决接口关联的三种方式

接口关联:接口2的入参需要接口1的返回值
(1).将关联值保存在类变量中(不能跨文件使用)
(2).将关联值保存在extract.yaml文件中。接口1写入关联值,接口2读取关联值
(3).封装请求类,测试用例数据中写{{access_token}},封装的请求类在实际发送请求时,会将{{access_token}}替换为extract.yaml的真实值

二、接口关联—将关联值保存在extract.yaml文件

接口1:上传图片,返回图片的URL
接口2:将图片上传至相册,需要接口1的图片URL

1、创建extract.yaml文件保存关联值

2、编写工具类读写extract.yaml中的值

    def read_extract_yaml(self,key):
        path="C:\\Users\\mingyuewu\\PycharmProjects\\mashang\\config\\extract.yaml"
        with open(path,mode="r",encoding="utf-8") as f:
            value = yaml.load(stream=f,Loader=FullLoader)
            #读取的value为字典格式
            return value[key]
    def write_extract_yaml(self,data):
        path="C:\\Users\\mingyuewu\\PycharmProjects\\mashang\\config\\extract.yaml"
        # data需为字典格式
        with open(path,mode="a+",encoding="utf-8") as f:
            yaml.dump(data,stream=f,allow_unicode=True)

    # 清空文件
    def clear_extract_yaml(self):
        path = "C:\\Users\\mingyuewu\\PycharmProjects\\mashang\\config\\extract.yaml"
        with open(path, mode="w", encoding="utf-8") as f:
            f.truncate()

3、接口上传图片、图片上传相册

    def test_login(self):
        url= "/api/login"
        data ={
                "username": "username",
                "password": "password"
        }
        res= RequestUtil().send_request("post", url=url,  data=data)
  
    def  test_upload_photo(self):
        # ConfigYamlUtil().clear_extract_yaml()
        url="/api/admin/photos/albums/cover"
        method = "post"
        files = {
            "file": ("1.webp", open("./1.webp", "rb"), "application/octet-stream")
        }
        res = RequestUtil().send_request(method=method, url=url, files=files)
        cover_url = jsonpath.jsonpath(res.json(), '$.data')[0]
        data = {"cover_url": cover_url}
        # 将关联值写入文件
        ConfigYamlUtil().write_extract_yaml(data)

    def test_upload_ablums(self):
        url="/api/admin/photos"
        method="post"
        headers = {
            "Content-Type ": "application/json;charset=UTF-8"
        }
        #从文件读取关联值
        cover_url=ConfigYamlUtil().read_extract_yaml("cover_url")
        data = json.dumps(
            {
                "albumId": "1",
                 "photoUrlList": [cover_url]
            }
        )
        res = RequestUtil().send_request(method=method, url=url, headers=headers, data=data)
        print(res.request.body)
        print(res.request.headers)

三、封装requestUtil类解析测试数据中的关联值

1、原理

使用extract.yaml处理接口关联时,是在用例方法中,写入/读取extract.yaml的关联值。
封装requestUtil处理接口关联时,是在requestUtil中添加方法,可以识别测试用例中的关联值。举例:上传图片到相册接口的测试数据photo_testdata.yaml文件如下:
(1)关联值cover_url用{{}}括起来,表示需要解析提取的值。
(2)requestUtil执行send_request方法时,使用参数化读取photo_testdata.yaml中的测试数据。
(3)requestUtil识别测试数据中是否有{{}}标识的变量,如果有则在extract.yaml文件种查找该变量对应的value,将{{}}标识的变量,替换为value

  data:
   albumId: 5
   photoUrlList: 
   -{{cover_url}}

2、代码

(1)、编写图片上传置接口测试数据upload_photo_album.yaml

-
 feature: 相册管理
 story: 上传接口
 title: 上传图片到相册
 request:
  method: post
  url: /api/admin/photos
  headers:
   Content-Type: application/json;charset=UTF-8
   Accept-Encoding: gzip, deflate
   User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36
   Referer: http://114.55.135.15:81/albums/5
  data:
   albumId: 5
   photoUrlList:
    - "{{cover_url}}"
 validate: success
 

(2)编写读取测试数据的文件

import yaml

class ReadTestdataYaml:
    def read_testdata(self,file_path):
        #file_path="C:\\Users\\mingyuewu\\PycharmProjects\\mashang\\testdatas\\upload_photo_ablum.yaml"
        with open(file_path,mode="r",encoding="utf-8") as f:
            value = yaml.load(f,Loader=yaml.FullLoader)
            return value

if __name__ =="__main__":
    file_path = "C:\\Users\\mingyuewu\\PycharmProjects\\mashang\\testdatas\\upload_photo_ablum.yaml"
    print(ReadTestdataYaml().read_testdata(file_path))

(3)封装RequestUtil

deal_variables方法将测试数据种{{}}标识的关联值解析为实际值
send_request种处理了url、headers、params、data、json几种传参方式值的替换

import requests
import json
from tools.config_yaml_util import ConfigYamlUtil

class RequestUtil():
    # 统一会话
    session = requests.session()
    # 获取被测系统的IP地址
    base=""
    # 从配置文件中读取对应IP
    def  __init__(self):
        RequestUtil.base = ConfigYamlUtil().read_config_yaml("url","blog_url")

    def deal_variables(self,data):
        '''
        :param 待处理含{{access_token}}的数据:
        :return: 返回将{{}}中的值处理为 extract.yaml文件中对应的实际值
        '''
        #1、将数据类型全部处理为string,保存在str变量中
        if data and isinstance(data,dict):
            str = json.dumps(data)
        else:
            str = data
        # url = "http://11.11.11.11:80/index?access_token={{access_token}}&cover_url={{cover_url}}"
        # 2、将{{variable}}中的数据替换为extract.yaml中的实际值
        for i in range(1, str.count("{{") + 1): #处理字符串中含多个{{}}的情况
            if "{{" in str and "}}" in str:
                start_index = str.index("{{")
                end_index = str.index("}}")
                before_var =str[start_index:end_index + 2]
                print("\n-------------------替换前{}".format(before_var))
                after_var = ConfigYamlUtil().read_extract_yaml(key=before_var[2:-2])
                print("-------------------替换后{}".format(after_var))
                str = str.replace(before_var, after_var)
                print("-------------------最终结果{}".format(str))
        # 3、数据类型还原
        if  data and isinstance(data,dict):
            data = json.loads(str)
        else:
            data = str
        return(data)
        
    def send_request(self,method,url,**kwargs):
        #1、将method处理为小写
        self.method = str(method).lower()
        #2、处理URL 拼接完整
        self.url= RequestUtil.base+url
        #3、将url中类似{{access_token}}的变量,替换为extract.yaml文件中实际的值
        self.url = self.deal_variables(self.url)
        #4、将headers,params,json,data参数中,类似{{access_token}}的变量,替换为extract.yaml文件中实际的值
        for key,value in kwargs.items(): # data ={"username":"{{}}","password"}  headers={}
            if key in ["headers","params","data","json"]:
                kwargs[key] = self.deal_variables(value) #kwargs[key]
        #5、发送请求
        res=RequestUtil.session.request(method=self.method,url=self.url, **kwargs)
        print(res.text)
        return res

4、测试用例类

 @pytest.mark.parametrize('casedata',ReadTestdataYaml().read_testdata("C:\\Users\\mingyuewu\\PycharmProjects\\mashang\\testdatas\\upload_photo_ablum.yaml"))
    def test_upload_ablums(self,casedata):
        url=casedata["request"]["url"]
        method=casedata["request"]["method"]
        headers = casedata["request"]["headers"]
        #cover_url=ConfigYamlUtil().read_extract_yaml("cover_url")
        data=casedata["request"]["data"]
        res = RequestUtil().send_request(method=method, url=url, headers=headers, data=json.dumps(data))
        print(res.request.body)
        print(res.request.headers)

你可能感兴趣的:(pytest,python)