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

准备工作

框架目录

base:请求方法

data:存放数据

utils:操作方法

log:日志

report:存放测试报告

tests:测试主程序

common:公共方法

在这里插入图片描述

封装请求方法

在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

测试报告打开效果

在这里插入图片描述

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章