一个简单的测试框架建成

写在前言:

本文所用项目来源于白月黑羽的白月SMS系统:Bysms 系统安装与运行 | 白月黑羽

仅用于框架搭建练习与回顾,不做其他性质操作。

如有僭越侵权,麻烦您私信联系删除。

基础内容

框架基于 python + requests + unittest + ddt

大致流程:从excel表格中拿数据,进行发送请求,对响应结果进行断言,将结果写入excel中。 

(事实上断言可以做数据库断言,这里不做设计)

from openpyxl import load_workbook


class ToolsExecl:

    def __init__(self,FileName):
        self.workbook = load_workbook(filename=FileName)
        # 实例化对象
        setattr(self,'FileName',FileName)
        # 将文件名字设置为类属性

    def open_execl(self, SheetName=None):
        # 从表格中读取数据
        try:
            if SheetName:
                sheet = self.workbook[SheetName]
                datas = list(sheet.iter_rows(values_only=True))
                data_list = []
                case_title = datas[0]
                case_datas = datas[1:]
                for case in case_datas:
                    result = dict(zip(case_title, case))
                    data_list.append(result)
                return data_list
                # 返回一个数据列表,内在元素为key:value 
        except Exception as e:
            print(f"读取{SheetName}表有误", e)
        finally:
            self.close_execl()

    def write_execl(self,SheetName, case_id, Text=None):
        # 将需要的内容写入excel中
        try:
            sheet = self.workbook[SheetName]
            datas = list(sheet.iter_rows(values_only=True))[0]
            datas = list(enumerate(datas, start=1))

            for data in datas:
                if data[1] == 'result':
                    setattr(ToolsExecl, 'column', int(data[0]))
            sheet.cell(row=int(case_id + 1), column=getattr(ToolsExecl, 'column'), value=Text)
            self.workbook.save(filename=getattr(self,'FileName'))
            print(sheet.max_row)
        except Exception as e:
            print("读取数据有误", e)
        finally:
            self.close_execl()

    def close_execl(self):
        # 关闭表格     
        self.workbook.close()


if __name__ == '__main__':
    pass

登录接口

Request URL: http://127.0.0.1/api/mgr/signin
Request Method: POST
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
username: byhy
password: 88888888

在excel表格中设计用例,填入以上请求必须项

(请求头可以单独设置,也可以不设置,这里只有这一个form表单请求所以不做单独设置。)

一个简单的测试框架建成_第1张图片 用例首行id编号,title标题,method请求方法,url请求地址,data请求参数,expect预期结果,result写入结果,作为数据提取字段传递参数;

用例只是简单举例设计,可以更加完善(如少参多参,有效无效参数)。

1.读取数据(通过封装好的ToolsExecl类读取数据)

2.发送请求(将需要的请求单独封装一个类,方便添加/减少参数)

3.对实际响应结果和预期结果做断言(封装一个类用于对结果断言)

4.通过写入结果pass,失败写入fail (ToolsExecl类中的write_execl)

发送请求封装一个类:发送请求方法

import requests


class ToolsRequest:
    def __init__(self):
        self.head = {"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}


    def send_request(self, method, url, data):
        resq = requests.request(method=method, url=url, data=data, headers=self.head)
        return resq
        # 返回一个对象,后续需要什么数据,可操作性大

响应结果处理,进行断言,写入数据对应ToolsExecl类中的write_execl方法

import json
from jsonpath import jsonpath

from TestTools.Tools_Execl import ToolsExecl


class ToolsRespone:
    def __init__(self,FileName):
        self.ToolsExecl=ToolsExecl(FileName=FileName)

    def tool_response(self, response):
        # 将结果包装成统一的格式
        try:
            if isinstance(response.json(), dict):
                return {"response": response.json()}
        except Exception as e:
            return {"response": response.text}

    def assert_response(self, response, expect, SheetName, case_id):
        response = self.tool_response(response=response)
        if expect:
            actual = {}
            expect = expect if isinstance(expect, dict) else json.loads(expect)
            for key in expect:
                actual[key] = jsonpath(response, f"$..{key}")[0]
            try:
                assert actual == expect
                self.ToolsExecl.write_execl(SheetName=SheetName, case_id=case_id, Text="pass")
            except Exception as e:
                self.ToolsExecl.write_execl(SheetName=SheetName, case_id=case_id, Text="fail")

框架执行代码就可以写成以下格式:

"""
代码执行处
"""
import unittest
from ddt import ddt,data

from TestTools.Tools_Execl import ToolsExecl
from TestTools.Tools_Requests import ToolsRequest
from TestTools.Tools_Respone import ToolsRespone


data_list = ToolsExecl(FileName=testdata_path).open_execl( SheetName="login")
# testdata_path 为自己放置excel表格的地址


@ddt
class TestSMS(unittest.TestCase):

    @classmethod
    def setUpClass(cls) -> None:
        cls.ToolsRequest = ToolsRequest()
        cls.ToolExtract = ToolExtract()
        cls.ToolsRespone = ToolsRespone(FileName=testdata_path)

    @data(*data_list)
    def testmethod(self, case):
        # 发送请求
        resq = self.ToolsRequest.send_request(method=case['method'], url=case['url'], data=case['data'])

        # 断言响应,并写入结果
        self.ToolsRespone.assert_response(response=resq, expect=case['expect'],
                                          SheetName="login", case_id=case['id'])


if __name__ == '__main__':
    unittest.main()

运行成功后可以看到excel表中result列写入了pass

一个简单的测试框架建成_第2张图片

 

客户接口

用例设计:

一个简单的测试框架建成_第3张图片

(简单设置用例,在有效无效/少惨多参/边界可以做文章)

# 添加客户
Request URL: http://127.0.0.1/api/mgr/customers
Request Method: POST
Content-Type: application/json
Cookie: sessionid=ygyhv302ke1gnncoghjzy8lkqw81g93x
接口响应:{"id":23,"ret":0}
# 修改客户
Request URL: http://127.0.0.1/api/mgr/customers
Request Method: PUT
Content-Type: application/json
Cookie: sessionid=ygyhv302ke1gnncoghjzy8lkqw81g93x
接口响应:{"ret":0}

# 删除客户

Request URL: http://127.0.0.1/api/mgr/customers
Request Method: DELETE
Content-Type: application/json
Cookie: sessionid=ygyhv302ke1gnncoghjzy8lkqw81g93x
响应:{"ret":0}

流程:先登录-保存cookie或token信息-后面请求接口带上请求头操作即可

保存cookie或者token新增一个类来实现,excel中也需要新增一列提取列 extract。

新增一个类ToolsAttribute,用于保存变量。

class ToolsAttribute:
    pass
import json
from jsonpath import jsonpath

from TestTools.Tools_Attribute import ToolsAttribute


class ToolExtract:
    # 提取cookie信息
    def extract_data(self, extract: str, response):
        # 从excel中来的数据均为str格式,response为响应对象,未做任何处理的对象
        if extract:
            extract = extract if isinstance(extract, dict) else json.loads(extract)
            for k, v in extract.items():
                if k == 'Set-Cookie':
                    value = response.headers[k]
                    setattr(ToolsAttribute, k, str(value))
                else:
                    value = jsonpath(response.json(), f"$..{k}")[0]
                    setattr(ToolsAttribute, k, value)
需要注意的细节:
1.只有登录的时候请求头为form,后续的数据请求头均为json,所以需要在请求头上进行修改;

2.添加成功后的相应信息{"id":23,"ret":0},其中id的value为int类型
最终流程为:
登录,提取cookie/token保存到请求头
添加客户,加上请求头,data转为对应类型,提取添加成功后的id信息
修改客户,加上请求头,替换data里的id
删除客户,加上请求头,替换data里的id
"""
请求代码示例
"""
import json
import requests

from TestTools.Tools_Attribute import ToolsAttribute


class ToolsRequest:
    def __init__(self):
        self.head = {"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}
        self.fk = Faker(locale="zh-CN")

    def __headers(self):
        if hasattr(ToolsAttribute, 'Set-Cookie'):
            # 处理请求头
            cookie = getattr(ToolsAttribute, 'Set-Cookie')
            headers = {"Content-Type": "application/json"}
            if 'cookie' not in self.head.keys():
                # 判断请求头中是否存在token
                headers['Cookie'] = cookie
                setattr(ToolsAttribute, 'cookie_head', headers)
            else:
                print('已有cookie,不需要再次设置请求头')

    def data_replace(self, data: str):
        if data:
            data = json.loads(data)
            for key, value in data.items():
                if key == "id":
                    data[key] = getattr(ToolsAttribute, key)
            return data
        else:
            print("data不存在,无需替换")
            return {}


    def send_request(self, method, url, data):
        self.__headers()
        data = self.data_replace(data=data)
        if "action" not in data.keys():
            resq = requests.request(method=method, url=url, data=data, headers=self.head)
        else:
            resq = requests.request(method=method, url=url, json=data, headers=getattr(ToolsAttribute, 'cookie_head'))
        return resq

代码基本成型,只需要完善细节和diy设计即可

后续的订单和药品接口也同理,只需在新增excel中新增对应表和数据即可。

结束:

这个简陋版的框架有许多的细节可以添加,如:请求头的设置,url的拆分,添加商品后对查询数据库进行断言,生成随机数据进行替换等,可以在此思路上逐渐发挥,完善代码

再次声明:

本文所用项目来源于白月黑羽的白月SMS系统:Bysms 系统安装与运行 | 白月黑羽

仅用于框架搭建练习与回顾,不做其他性质操作。

如有僭越侵权,麻烦您私信联系删除。

你可能感兴趣的:(python)