欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

API测试框架设计---基于Pytest

程序员文章站 2023-12-27 14:03:57
...

准备工作

框架目录

base:请求方法

data:存放数据

utils:操作方法

log:日志

report:存放测试报告

tests:测试主程序

common:公共方法

API测试框架设计---基于Pytest

封装请求方法

在base目录下创建requests.py文件 将常用请求方法 封装

import requests
"""请求方法的封装"""
class request:
    def request(self,url,method='post',**kwargs):
        '''
        :param url: 请求地址
        :param method: 请求方法
        :param kwargs: 请求参数
        :return:
        '''
        if method == 'post':
            return requests.request(url=url,method=method,**kwargs)
        elif method == 'get':
            return request.request(url=url,method='get',**kwargs)
        elif method == 'put':
            return requests.request(url=url,method='put',**kwargs)
        elif method == 'delete':
            return request.request(url=url,method='delete',**kwargs)

    def post(self,url,**kwargs):
        return self.request(url=url,method='post',**kwargs)

    def get(self,url,**kwargs):
        return  self.request(url=url,**kwargs)

    def put(self,url,**kwargs):
        return self.request(url=url,method='put',**kwargs)

    def delete(self,url,**kwargs):
        return self.request(url=url,method='delete',**kwargs)

封装查找文件路径公共

在base目录下创建公共方法pubilc.py

import os
def dir_path(filepath='data',filename =None):
    """
    :param filepath: 文件路径
    :param filename: 文件名称
    :return:
    """
    return os.path.join(os.path.dirname(os.path.dirname(__file__)),filepath,filename)

对Excel操作方法进行封装

在utils目录下创建方法operationExcel.py文件

import xlrd
from common.pbulc import *

class ValueExcels:
    caseID = 0
    des = 1
    url = 2
    method = 3
    data = 4
    expect = 5


    def CaseID(self):
        return self.caseID

    def description(self):
        return self.des

    def Url(self):
        return self.url

    def Method(self):
        return self.method

    def Data(self):
        return self.data

    def Expect(self):
        return self.expect

class OperationExcel():
    # valueExcels = ValueExcels()

    def get_excel(self):
        '''打开Excel文件'''
        db = xlrd.open_workbook(dir_path(filename='data.xls'))
        sheet = db.sheet_by_index(0)
        return sheet

    def get_row(self):
        '''获取Excel有多少行内容'''
        return self.get_excel().nrows

    def getValue(self,row,cel):
        return self.get_excel().cell_value(row,cel)

    def getCaseID(self,row):
        '''获取caseid列'''
        return self.getValue(row,ValueExcels().CaseID())

    def getURL(self,row):
        return self.getValue(row,ValueExcels().Url())

    def getdata(self,row):
        return self.getValue(row,ValueExcels().Data())

    def getmethod(self,row):
        return self.getValue(row,ValueExcels().Method())




o = OperationExcel()
# print(o.getValue(1,ValueExcels().Url()))
print(o.getCaseID(1))
print(o.getURL(1))
print(o.getdata(1))
print(o.getmethod(1))

操作yaml文件

在utils目录下创建操作yaml文件的方法

import yaml
from common.pbulc import *
class Operationyaml():

    def dictyaml(self,filepath='data',filename='login.yaml'):
        with  open(dir_path(filepath=filepath,filename=filename),'r',encoding='utf-8') as f:
            return yaml.safe_load(f)
o = Operationyaml()
print(o.dictyaml())
>>>{'data_01': {'phone': 11123412312, 'password': 123456}}

获取yaml文件中的请求参数

修改utils文件夹下operationexcel文件 getdata方法取值方法

要获取yaml文件中,如:data_01对应的value参数 要利用excel中data列的值 建立一个映射关系 获取yaml文件中的参数

import xlrd
from common.pbulc import *
from utils.operationyaml import Operationyaml#导入yaml文件
class ValueExcels:
    caseID = 0
    des = 1
    url = 2
    method = 3
    data = 4
    expect = 5


    def CaseID(self):
        return self.caseID

    def description(self):
        return self.des

    def Url(self):
        return self.url

    def Method(self):
        return self.method

    def Data(self):
        return self.data

    def Expect(self):
        return self.expect

class OperationExcel(Operationyaml):#继承Operationyaml类

    def get_excel(self):
        '''打开Excel文件'''
        db = xlrd.open_workbook(dir_path(filename='data.xls'))
        sheet = db.sheet_by_index(0)
        return sheet

    def get_row(self):
        '''获取Excel有多少行内容'''
        return self.get_excel().nrows

    def getValue(self,row,cel):
        return self.get_excel().cell_value(row,cel)

    def getCaseID(self,row):
        '''获取caseid列'''
        return self.getValue(row,ValueExcels().CaseID())

    def getURL(self,row):
        return self.getValue(row,ValueExcels().Url())

    def getdata(self,row):
        # print(self.getValue(row, ValueExcels().Data()))
        #在这里 利用字典取值key:value的方式 将excel中key对应的yaml文件中的参数取到
        return self.dictyaml()[self.getValue(row, ValueExcels().Data())]

    def getmethod(self,row):
        return self.getValue(row,ValueExcels().Method())


o = OperationExcel()
print(o.getdata(2))
>>>{"page":1}

测试主方法

tests目录下创建test_API.py文件

把请求方法 操作文件的方法 全部导入 发送API请求

from base.mthod import request
from utils.operationExcel import OperationExcel
from utils.operationyaml import Operationyaml
import pytest
import json
class TestRun:
    excel = OperationExcel()
    obj = request()

    def test_YLMY_login(self):
        """登录"""
        r = self.obj.post(
            url=self.excel.getURL(1),
            data=self.excel.getdata(1)
        )
        print(r.json())
      
if __name__ == '__main__':
    pytest.main('-v','test_API.py')        

token的处理

在登录请求获取写入文件

pubilc路径下写一个 写入方法,写入文件的目录在默认的data路径下 一会儿在登录接口调用这个方法 将token写入txt文件

def writetoken(contest):
    """
    :param contest: 写入内容的形参
    :return:
    """
    with open(dir_path(filename='token.txt'),'w') as f:
        f.write(contest)

登录接口调用文件写入方法

from common.pbulc import *
def test_YLMY_login(self):
    """登录"""
    r = self.obj.post(
        url=self.url() + self.excel.getURL(1),
        data=self.excel.getdata(1)
    )
    
    writetoken(json.dumps({"token":r.json()['data']['token']}))

查找token.txt文件路径

在utils目录下创建readlinetoken.py文件

from common.pbulc import *
def dir_token():
    db = dir_path("data",'token.txt')
    return db

def get_token():
    file =open(dir_token(),'r')
    token = file.readline()
    file.close()
    return token

在其他接口请求中使用token

from base.mthod import request
from utils.operationExcel import OperationExcel
from utils.operationyaml import Operationyaml
from utils.readlinetoken import get_token #导入查找token文件路径方法
import pytest
import json
class TestRun:
    excel = OperationExcel()
    obj = request()

    def test_YLMY_login(self):
        """登录"""
        r = self.obj.post(
            url=self.excel.getURL(1),
            data=self.excel.getdata(1)
        )
        print(r.json())
        writetoken(json.dumps({"token":r.json()['data']['token']}))
    def test_YLMY_info(self):
        """我的"""
        r = self.obj.post(
            url=self.excel.getURL(2),
            headers=json.loads(get_token())  #拼接headers
        )
        print(json.dumps(r.json(),indent=True,ensure_ascii=False))
if __name__ == '__main__':
    pytest.main('-v','test_API.py')        

断言

在Excel表期望结果列中写入结果与返回数据进行对比

在excel表中第一行预期结果中写入msg对应的登录成功 然后写断言

def test_YLMY_login(self):
    """登录"""
    r = self.obj.post(
        url=self.url() + self.excel.getURL(1),
        data=self.excel.getdata(1)
    )
    assert self.excel.getexpect(row=1) in json.dumps(r.json(),ensure_ascii=False)
    writetoken(json.dumps({"token":r.json()['data']['token']}))

这个断言在每个接口中都会使用 所以封装成一个方法 方便调用

def result(self,r,row):
    """
    :param r: 实际结果
    :param row:预期结果所在行
    :return:断言方法
    """
    assert r.status_code == 200
    assert self.excel.getexpect(row=row) in json.dumps(r.json(),ensure_ascii=False)

def test_YLMY_login(self):
    """登录"""
    r = self.obj.post(
        url=self.url() + self.excel.getURL(1),
        data=self.excel.getdata(1)
    )
    # assert self.excel.getexpect(row=1) in json.dumps(r.json(),ensure_ascii=False)
    self.result(r=r,row=1)#调用result断言方法
    writetoken(json.dumps({"token":r.json()['data']['token']}))

URL路径分离

测试环境和生产环境只是域名 不同 后面的路径都是相同的所以 在测试后测试环境后 在线上环境测试还要改域名 太麻烦 现在把excel表里的域名 分离出来 放到一个公共方法里 这样在测试和正式环境 切换时 就只需要改一个就可以了

在操作operationexcel.py 文件中的geturl方法中 修改url获取方法 把前面的域名和excel表中的路径拼接起来

    def getURL(self,row):
        url = "http://127.0.0.1:5000" + self.getValue(row,ValueExcels().Url())
        return url
        # return self.getValue(row,ValueExcels().Url())

主方法不用改变 直接请求 这样切换测试环境时 只需要改一次就可以了

def test_YLMY_login(self):
    """登录"""
    r = self.obj.post(
        url=self.excel.getURL(1),
        data=self.excel.getdata(1)
    )
    # assert self.excel.getexpect(row=1) in json.dumps(r.json(),ensure_ascii=False)
    self.result(r=r,row=1)
    writetoken(json.dumps({"token":r.json()['data']['token']}))

请求参数化

一个页面的接口有很多个page页 要测试 又不可能封装好几个用例 这样可以将page重构成动态的

用更改字典k值的方式 将参数构造成动态的

from utils.operationExcel import OperationExcel
excel= OperationExcel()

def getpage(page):
    dict1= excel.getdata(3)
    dict1['page']=page
    return dict1

导入上面的操作函数 在data参数上调用 然后传入什么参数就是什么参数了

def test_YLMY_index(self):
    """首页"""
    r =self.obj.post(
            url=self.excel.getURL(3),
            data = getpage(2)
        )
        print(p)
        print(r.status_code)

我想一次测试完page1到page5可以把参数放到列表里 然后for循环传入即可

ef test_YLMY_index(self):
    """首页"""
    page = [1,2,3,4,5]
    for p in page:
        r =self.obj.post(
            url=self.excel.getURL(3),
            data = getpage(p)
        )
        print(p)
        print(r.status_code)

测试报告

Allure生成HTNL测试报告

配置工作:

1、下载地址:http://allure.qatools.ru/

2、下载完成解压后将bin目录的路径添加到path环境变量中

3、DOS命令输入 allure验证是否完成 如果没有报错 说明没问题

4、输入 pip install allure-pytest 安装这个库

生成在线测试报告

执行测试 并使用Allure侦听器在测试执行期间收集结果 --alluredir 提供存储结果的路径

pytest  -v  test_API.py --alluredir=/report

打开测试报告

allure serve /report

测试报告打开效果

API测试框架设计---基于Pytest

同一个网段下的设备输入本机ip端口号也能访问

上一篇:

下一篇: