目录
1.场景
查询商铺列表和修改商铺信息
2.相关接口
(1)获取列表
(2)更新修改
(2.1)图片上传
3.代码
(1)yaml配置接口信息
Shop: #用户--类级别
query: #用户列表--函数级别
url: /shopping/myShop
method: GET
file_upload: #文件上传接口
url: /file
method: POST
update: # 修改接口
url: /shopping/updatemyshop
method: POST
(2)BaseAPI基类封装方法
query、update、file_upload
import requests
import inspect#获取类或者函数的参数信息
from utils.handle_yaml import get_yaml_data
from configs.config import HOST
#每个类都继承
class BaseApi:
def __init__(self,token=None):
if token:#其他需要token鉴权的接口
self.header={'Authorization':token}
else:
self.header=None
#谁调用,就通过类名作为键,获取对应的类的数据
#获取继承BaseAPI的子类的类名self.__class__.__name__
self.data=get_yaml_data('../data/apiConfig.yaml')[self.__class__.__name__]
def request_send(self,inData,json=None,file=False):
try:
funcName=inspect.stack()[1][3]
print("调用我的的函数名》",funcName)
data=self.data[funcName]
print("===me==",data['method'])
# 如果是file!=None,是文件上传接口
if file:
resp = requests.request(data['method'], url=f'{HOST}' + data['url'],
files=inData, headers=self.header)
else:
#当接口支持post以参数传递时(url+&),用params
resp = requests.request(data['method'], url=f'{HOST}' + data['url'],
params=inData, headers=self.header)
print(resp)
return resp.json()
except Exception as error:
#写日志:调用日志的方法
raise error#抛出异常给上一层框架--pytest
#----查询接口---
def query(self,inData):
return self.request_send(inData)
# ----更新接口---
def update(self,inData):
return self.request_send(inData)
#----文件上传接口---
#如果pycharm不提示,就加上str
def file_upload(self,fileDir:str):
#(文件名称,文件对象,文件类型)--固定写法,rb是二进制
fileName=fileDir.split('\\')[-1]
fileType=fileName.split('.')[-1]
userFile={'file':(fileName,open(fileDir,'rb'),fileType)}#请求体
print("文件路径==》",)
return self.request_send(userFile,file=True)
# --------断言类封装-----
class BaseAssert:
@classmethod#使用类名就可以直接调用类方法
def define_assert(cls,res,expData):
try:
assert res==expData
except Exception as error:
#打日志-之后补充
raise error
(3)Shop业务操作代码
from common.baseApi import BaseApi
from libs.login import Login
from configs.config import NAME_PSW
from utils.handle_path import data_path
"""
店铺模块:
1.列出接口
2.编辑接口
(1)图片上传接口
"""
class Shop(BaseApi):
#方法重写
def update(self,inData,shopID,imageInfo):
"""
:param inData: excel测试用例里的请求数据--字典类型
:param shopID: 查询接口获真实店铺id
:param imageInfo: 图片上传接口获取的真实的图片信息
:return:
"""
#更新店铺id
inData['id']=shopID
#修改图片信息
inData['image_path']=imageInfo
inData['image']=f'/file/getImgStream?fileName={imageInfo}'
#父类方法调用
#super(该子类的类名,self)---这种写法适合多继承
return super(Shop,self).update(inData)
if __name__ == '__main__':
# 1.登录操作-获取token
token = Login().login(NAME_PSW,getToken=True)
# 2.查询商铺
testData={"page":1,"limit":2}
# 创建Shop实例
shop=Shop(token)
res1=shop.query(testData)
print(res1)
shopID = res1['data']['records'][0]['id']
print("店铺id>>", shopID)
# 3.图片上传
resimage=shop.file_upload(data_path+'\\cat.jpg')
#res=shop.file_upload(data_path+r'\cat.jpg')或者这样写
print("图片上传接口》",resimage)
# 4.验证编辑更新店铺信息接口
testData={
"name":"星巴克",
"adress":"上海",
"id":"333",
"Phone":"13456789",
"rating":"6.0",
"recent_order_num":100,
"category":"饮品",
"description":"满30减5",
"image_path":"cat.jpg",
"image":"http://waimai.com/file/getImgStream?fileName=cat11.jpg"
}
imageInfo=resimage['data']['realFileName']
res=shop.update(testData,shopID,imageInfo)
print("测试结果》",res)
(4)自动化测试
conftest.py
import pytest
from libs.login import Login
from libs.shop import Shop
from configs.config import NAME_PSW
@pytest.fixture(scope='session',autouse=True)
def start_running():
print("外卖接口自动化测试====start=====")
yield#后面的代码是所有用例执行完之后需要做的事情
print("外卖接口自动化测试----end------")
@pytest.fixture(scope='class')
def login_init():
token=Login().login(NAME_PSW,getToken=True)
#yield和return都是返回值操作,yield之后可以继续写代码
yield token
print('登录初始化操作完成====')
# 如果一个fixture需要使用另一个fixture的返回值,直接使用这个fixture的函数名
@pytest.fixture(scope='class')
def shop_init(login_init):
print('---创建店铺初始化操作---')
# 创建店铺实例 需要一个token值
shopObject=Shop(login_init)
yield shopObject #返回店铺实例
print('---创建店铺初始化完成---')
test_shop.py文件及with allure.step使用
import pytest,allure,os
from libs.login import Login
from utils.handle_excel import get_excel_data
from utils.handle_path import report_path
from utils.handle_path import data_path
from common.baseApi import BaseAssert
#TestLogin继承BaseAssert
@allure.epic('项目名称')
@allure.feature('业务模块名称')
class TestShop(BaseAssert):
@pytest.mark.parametrize('inBody,expData', get_excel_data('商铺模块', 'Listshop','请求参数','响应预期结果'))
@allure.story('商铺接口')
@allure.title('用例标题2')
def test_shop_list(self,inBody,expData,shop_init):#shop_init初始化操作
# 1.调用业务层封装的接口代码
res=shop_init.query(inBody)
# 2.断言实际返回结果与预期结果
self.define_assert(res['code'],expData['code'])
@pytest.mark.parametrize('inBody,expData', get_excel_data('商铺模块', 'Updateshop','请求参数','响应预期结果'))
def test_shop_update(self,inBody,expData,shop_init):
# 分步走
with allure.step('1.店铺实例'): #店铺实例
print('1.获取店铺实例')
with allure.step('2.店铺列出接口获取shopid'): #店铺列出接口获取shopid
shopID=shop_init.query({"page":1,"limit":2})['data']['records'][0]['id']
with allure.step('3.图片上传接口'):# 图片上传接口
resimage = shop_init.file_upload(data_path + '\\cat.jpg')
imageInfo = resimage['data']['realFileName']
with allure.step('4.调用编辑店铺接口'):
res=shop_init.update(inBody,shopID,imageInfo)
self.define_assert(res['code'],expData['code'])
if __name__ == '__main__':
pytest.main([__file__,'-sv','--alluredir',report_path,'--clean-alluredir'])
os.system(f'allure serve {report_path}')
测试报告: