侧边栏壁纸
  • 累计撰写 31 篇文章
  • 累计创建 14 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

从0到1搭建接口自动化框架

AllyTester
2024-11-02 / 0 评论 / 0 点赞 / 56 阅读 / 0 字

接口自动化允许测试人员提前介入脚本编写,从而缩短测试周期,能有效降低回归成本、用例执行成本,还可实现线上定时巡检功能等,在实际工作中具有非常大的应用价值。因此,基于以往测试经验,总结了使用unittest从0到1搭建接口自动化框架的方法步骤。

step1:搭建基础框架

1. 外层目录结构

  • business:业务层通用方法

  • common:通用方法封装

  • logs:日志存储

  • data:配置存储

  • testCase:用例集

  • main:项目执行入口

step2:实现common方法

1. 实现日志生成方法,满足用例的日志输出和日志存储的方法

def case_demo(text):
    """
    打印用例信息并输出对应的日志
    :param text: str 控制台要输出的内容或要打印的日志文本数据
    :return:
    """
    formatted_time = datetime.now().strftime('%H:%M:%S:%f')[:-3]  # 日志的输出时间
    stack = inspect.stack()
    code_path = f"{os.path.basename(stack[1].filename)}:{stack[1].lineno}"  # 当前执行文件的绝对路径和执行代码行号
    content = f"[CASE]{formatted_time}-{code_path} >> {text}"
    print(Fore.LIGHTCYAN_EX + content)
    str_time = datetime.now().strftime("%Y%m%d")
    with open(file=DIR + '\\logs\\' + f'{str_time}_info.log', mode='a', encoding='utf-8') as f:
        f.write(content + '\n')

2. 实现通用断言方法,满足接口返回体的断言方法

import unittest
from common.caseOutput import error
​
​
class AssertCommon(unittest.TestCase):
    def code_assert(self, expect, actual):
        if expect != actual:
            text = f'res code different, expect code: {expect}, actual code: {actual}.'
            error('assert fail! ' + text)
            self.fail(text)
​
    def __assertEqual(self):
        pass
​
    def json_assert(self, expect, actual):
        """
        json通用断言方法
        :param expect: 定义预期返回体
        :param actual: 实际返回的json
        :return: 断言成功返回None,断言失败触发fail
        """
        # 字段是否存在的校验
        for key, value in expect.items():
            self.assertIn(key, actual.keys())
        # 校验是否存在多余的字段
        self.assertEqual(len(expect.keys()), len(actual.keys()),
                         msg=f'response keys len different, response keys have: {list(actual.keys())}')
        for key, value in expect.items():
            # 进行数据类型的校验
            if isinstance(value, type):
                self.assertEqual(value, type(actual[key]),
                                 msg=f'{key} type error! actual type is {str(type(actual[key]))}')
            elif isinstance(value, list):
                for i in range(len(value)):
                    if isinstance(value[i], type):
                        self.assertEqual(value[i], type(actual[key][i]),
                                         msg=f'list element {actual[key][i]} type different, actual response {actual[key]}')
                    elif isinstance(value[i], dict):
                        self.json_assert(value[i], actual[key][i])
                    else:
                        self.assertEqual(value[i], actual[key][i],
                                         msg=f'list element {actual[key][i]} value different, actual response {actual[key]}')
            else:
                self.assertEqual(value, actual[key],
                                 msg=f'{key} value error! actual value is {str(actual[key])}')

3. 实现yaml配置读取方法,满足不同维度配置的读取,并且实现环境切换的方法

def config_load():
    """读取配置信息的方式"""
    with open(file=f'{DIR}/data/envConfig/{ENVIRON}/config.yml', mode='r', encoding='utf-8') as f:
        return yaml.load(f, Loader=yaml.FullLoader)

step3:main实现

1. 用例批量执行方法

使用unittest下的TestLoader、TestSuite、TextTestRunner实现用例的批量装载和执行。

import unittest
​
suite = unittest.TestLoader().discover('./testCase', 'test*.py')
​
runner = unittest.TextTestRunner()
runner.run(suite)

2. 定义全局变量

当前目录路径、环境变量等。

3. 报告的生成

常见的报告生成方法:HTML报告(HtmlTestRunner、BeautifulReport)、allure等。

4. 控制不同执行维度

用例的执行维度最好可以控制,使得测试工作在不同测试阶段更加灵活,比如冒烟测试时,更关注主流程场景的测试用例执行情况。

if __name__ == '__main__':
    run_pattern = 'all'  # all 全量测试用例执行 /  smoking 冒烟测试执行  /  指定执行文件
    if run_pattern == 'all':
        pattern = 'test_*.py'
    elif run_pattern == 'smoking':
        pattern = 'test_major.py'
    else:
        pattern = run_pattern + '.py'
    suite = unittest.TestLoader().discover('./testCase', pattern=pattern)
    result = BeautifulReport(suite)
    result.report(filename="report.html", description='测试报告', report_dir='./')

step4:转换所有主流程测试用例

  • 实现用例的前置条件

  • 实现用例结果的断言方法

  • 遵循用例的编码规范:

①模块的定义,按接口拆分包,按用例级别拆分模块

②定义方法名 ,如:test01_remove_key

③用例描述,“”“XXXX”“”

④所有步骤需要通过日志中的step声明步骤过程

⑤断言方法复用common封装好的能力

step5:business实现

  • 封装接口协议的调用方法

  • 封装数据初始化的方法

  • 封装数据源的断言方法

  • 封装数据的清理方法

step6:主流程复用business的能力

  • setup实现数据清理方法

  • 实现数据初始化方法和断言方法

step7:编写input测试用例

  • 通用测试点实现参数化

  • 非通用测试点直接输出测试用例

step8:编写全量的handle测试用例

0

评论区