python+unittest+ddt+requests自动化数据驱动接口测试框架搭建,HTMLTestRunner生成测试报告

本文分享的是接口自动化测试框架搭建(主要围绕的是接口的测试用例开展),在今后的学习过程中会不断完善,话不多说,我们先来看看最终用HTMLTestRunner生成的测试报告吧。
python+unittest+ddt+requests自动化数据驱动接口测试框架搭建,HTMLTestRunner生成测试报告_第1张图片
接下来开启我们的搭建之旅
首先我们先来了解它的结构目录:
python+unittest+ddt+requests自动化数据驱动接口测试框架搭建,HTMLTestRunner生成测试报告_第2张图片
我们先来搭建common下的两个封装模块:
excel_handler和requests_handler,excel_handler简单的来说是读取我们表格里的数据,接下来我们先了解表格里面主要有哪些数据。
在这里插入图片描述
excel_handler.py

# 导入工具类
from openpyxl import load_workbook
# 定义打开Excel类
from openpyxl.worksheet.worksheet import Worksheet


class ExcelHandler:
    """操作Excel"""
    def __init__(self, file):
        """初始化,定义路径"""
        self.file = file

    def open_sheet(self, sheet_name) -> Worksheet:
        """
        打开表单
        在函数或者方法的后面加 -> 类型:表示此函数返回值是这样的类型
        """
        wb = load_workbook(self.file) # 打开Excel
        # 打开表单
        sheet = wb[sheet_name]
        wb.close()
        return sheet

    def header(self,sheet_name):
        """获取数据"""
        # 打开表单
        sheet = self.open_sheet(sheet_name)
        header = []
        for i in sheet[1]:
            header.append(i.value)  #获取值
        return header

    def read(self, sheet_name):
        """读取所有的数据"""
        sheet = self.open_sheet(sheet_name)

        rows = list(sheet.rows)
        # rows = list(sheet.rows)[1:] # 得到一个生成器,用list转换

        data = [] # 定义列表,存储数据列表
        for row in rows[1:]:
            row_data = [] # 获取数据列表
            for cell in row: # 加载
                # print(cell.value) # 获取数据
                row_data.append(cell.value) # 添加数据进去
                # 列表转换成字典:要和header去zip
                data_dict = dict(zip(self.header(sheet_name),row_data))
            data.append(data_dict)
        return data


    # def write(self,shett_name,row,column,data):
    #     """写入Excel数据"""
    #     sheet = self.open_sheet(shett_name)
    @staticmethod
    def write(file,sheet_name,row,column,data):
        """写入Excel数据"""
        wb = load_workbook(file)
        sheet = wb[sheet_name]
        # 修改单元格
        sheet.cell(row,column).value = data
        # 保存
        wb.save(file)
        # 关闭
        wb.close()

requests_handler.py

import requests
class RequestsHandler:
    def __init__(self):
        self.session = requests.Session()

    def visit(self,url,method, params=None,data=None,json=None, **kwargs):
        """
        访问一个接口,你可以使用get请求,也可以使用post请求,put,delete
        请求方法:mothod:
        请求地址:url
        请求参数:parsms,data,json
        :param url:
        :param method:
        :param params:
        :param data:
        :param json:
        :return:
        """
        # if method.lower() == "get":
        #     res = self.session.get(url,params=params,data=data,**kwargs)
        # elif method.lower() == "post":
        #     res = self.session.post(url,params=params,data=data,json=json,**kwargs)
        # else:
        # 可以处理请求方法
        res = self.session.request(method,url,params=params,data=data,json=json, **kwargs)
        try:
            return res.json()
        except ValueError:
            print("not json")

修改ddt(只是修好下面的一小部分),可以使用官方的。都没有问题哈。

    def wrapper(cls):
        for name, func in list(cls.__dict__.items()):
            if hasattr(func, DATA_ATTR):
                for i, v in enumerate(getattr(func, DATA_ATTR)):
                    test_name = mk_test_name(
                        name,
                        getattr(v, "__name__", v),
                        i,
                        fmt_test_name
                    )
                    if isinstance(v,list):
                        test_name = mk_test_name(name, v[2],i)
                    elif isinstance(v,dict):
                        test_name = mk_test_name(name,v["case_name"],i)
                    test_data_docstring = _get_test_data_docstring(func, v)
                    if hasattr(func, UNPACK_ATTR):
                        if isinstance(v, tuple) or isinstance(v, list):
                            add_test(
                                cls,
                                test_name,
                                test_data_docstring,
                                func,
                                *v
                            )
                        else:
                            # unpack dictionary
                            add_test(
                                cls,
                                test_name,
                                test_data_docstring,
                                func,
                                **v
                            )
                    else:
                        add_test(cls, test_name, test_data_docstring, func, v)
                delattr(cls, name)
            elif hasattr(func, FILE_ATTR):
                file_attr = getattr(func, FILE_ATTR)
                process_file_data(cls, name, func, file_attr)
                delattr(cls, name)
        return cls

封装好requests_handler.py和excel_handler.py后,我们就可以进行测试模块的脚本编写啦,这里以登录测试为例子,用例的格式如图片中表格的数据,如果有别的需求,进行相应的修改即可。
test_login.py

"""
ddt:数据驱动思想:data driven testing
现在所说的是一个叫做ddt的python库
ddt 库是和unittest搭配起来一起使用的,是unittest的一个插件
@ddt.ddt
class TestDemo:
    @ddt.data()
    def test_demo(self):
        pass
"""

# 导入工具包
import unittest
# import ddt
from 模块所在的路径 import ddt
from 类所在的模块路径 import ExcelHandler
from  类所在的模块路径 import RequestsHandler


test_data = ExcelHandler(r"测试表格存放的绝对路径").read('')
@ddt.ddt
# 封装类
class TestLogin(unittest.TestCase):

    # def setUp(self) -> None:
    # 前置条件
    # 每一个测试用例方法执行之前都会运行的代码
    def setUp(self):
        pass

    def tearDown(self):
        print("测试用例执行完毕。")
    @ddt.data(*test_data)
    #将*test_data当中的一组测试数据赋值到data
    def test_login_success(self,data):
        """读取数据进行测试"""
        res = RequestsHandler().visit(
                data['url'],
                data['method'],
                json=eval(data['data']),
                headers = eval(data["headers"]))

        self.assertEqual(res['msg'], data['expected'])

上边的准备完毕后,想要生成一份优质的网页版测试报告还需要进行一些简单的操作,当然,如果你的环境已经配置好了就不用啦。unittestreport安装
cmd命令行下输入下面的命令进行安装
pip install unittestreport
也可以在开发者工具中安装
接下来我们就可以编写我们的运行脚本(run_test.py)
run_test.py

import os
import unittest
import time
from unittestreport import TestRunner

# 初始化 testloader
testloader = unittest.TestLoader()  # 加载器

# 查找测试用例,加载
dir_path = os.path.dirname(os.path.abspath(__file__))  # 获取当前路径
case_path = os.path.join(dir_path,'test_casee') # 路径拼接

suite = testloader.discover(case_path) # 找到指定目录下所有测试模块,并可递归查到子目录下的测试模块,只有匹配到文件名才能被加载。

print(suite)

report_path = os.path.join(dir_path,'report')
if not os.path.exists(report_path):
    os.mkdir(report_path)

# 保存文件的时间戳
ts = str(int(time.time()))

file_name = 'test_result_{}.html'.format(ts)

file_path = os.path.join(report_path, file_name)

runner = TestRunner(suite)
runner.run()

上述时间戳的文件保存方式,可自行完善。
由于本小白还在学习的过程中,写得不好请勿喷,如果您们有更好的建议,欢迎讨论。

你可能感兴趣的:(接口测试,python,软件测试)