Pytest 测试框架实战

霍格沃兹测试开发

ceshiren.com

课程准备

  • 录播:
    • Python 编程语言
    • Pytest 测试框架
    • Allure2 测试报告
  • 环境准备:Python 环境、Pytest、Allure
  • 学习路线

目录

  • pytest 测试框架介绍
  • 知识点梳理
  • 实战演练

pytest 测试框架介绍

  • 测试发现:从多个文件中找到测试用例。
  • 测试执行:按照一定的顺序和规则去执行用例,并生成结果。
  • 测试判断:通过断言判断预期结果和实际结果的差异。
  • 测试条件:给定一些前置和后置的条件。
  • 测试报告:统计测试进度、耗时、通过率,生成测试报告。

知识点梳理

实战练习

  • 业务场景:
    • 计算器场景。
  • 需求:
    • 支持加法和除法。
    • 被测方法需要传递的数据类型为整型或者浮点型。
    • 数据区间为 [-99,99]。
    • 浮点数允许小数点后两位。

被测代码分析


class Calculator:
    def add(self, a, b):

        if a > 99 or a < -99 or b > 99 or b < -99:
            print("请输入范围为【-99, 99】的整数或浮点数")
            return "参数大小超出范围"

        return a + b

    def div(self, a, b):
        if a > 99 or a < -99 or b > 99 or b < -99:
            print("请输入范围为【-99, 99】的整数或浮点数")
            return "参数大小超出范围"

        return a / b

测试用例设计

  • 编写计算器中加法相应的测试用例。

加法测试用例

代码实现

  • 用例中要添加断言,验证结果。
  • 使用参数化实现测试数据的动态传递。
  • 灵活使用测试装置:
    • 在调用每个测试方法之前打印日志【开始计算】。
    • 在调用测试方法之后打印日志【结束计算】。
    • 调用完所有的测试用例最终输出日志【结束测试】。
# test_add.py
class TestAdd:

    def setup_class(self):
        self.calc = Calculator()

    def setup(self):
        logger.info("开始计算")

    def teardown(self):
        logger.info("结束计算")

    def teardown_class(self):
        logger.info("====>>>结束测试")

    @pytest.mark.parametrize(
      "a,b,expect",
      [
        [1, 1, 2],
        [-0.01, 0.02, 0.01],
        [10, 0.02, 10.02]
      ]
    )
    def test_add(self, a, b, expect):
        # 日志信息
        logger.info(f"a={a}, b= {b}, expect={expect}")
        # 测试步骤
        result = self.calc.add(a, b)
        # 日志信息
        logger.info(f"实际结果为:{result}")
        # 断言
        assert result == expect

实战练习 1

  • 数据驱动:
    • 创建数据文件:保存测试数据。
    • 创建解析文件方法:解析 yaml 中的数据
    • 用例中使用解析之后的数据。
  • 执行完所有的用例,清理所有的测试数据。
  • 生成测试报告。

测试数据文件

add:
  P0:
    datas:
      - [1, 1, 2]
      - [-0.01, 0.02, 0.01]
      - [10, 0.02, 10.02]
    ids:
      - 2个整数
      - 2个浮点数
      - 整数+浮点数
  P1_1:
    datas:
      - [98.99, 99, 197.99]
      - [99, 98.99, 197.99]
      - [-98.99, -99, -197.99]
      - [-99, -98.99, -197.99]
      - [99.01, 0, "参数大小超出范围"]
      - [-99.01, -1, "参数大小超出范围"]
      - [2, 99.01, "参数大小超出范围"]
      - [1, -99.01, "参数大小超出范围"]
    ids:
      - 有效边界值相加【98.99,99】
      - 有效边界值相加【99,98.99】
      - 有效边界值相加【-98.99,-99】
      - 有效边界值相加【-99,-98.99】
      - 无效边界值相加【99.01,0】
      - 无效边界值相加【-99.01,-1】
      - 无效边界值相加【2,99.01】
      - 无效边界值相加【1,-99.01】
  P1_2:
    datas:
      - [文, 9.3, "TypeError"]
      - [4, 字, "TypeError"]
      - [nu, 0.2, "TypeError"]
      - [30, t, "TypeError"]
      - ["*&", 0.2, "TypeError"]
      - [21.45, "@", "TypeError"]
    ids:
      - 第一个值是汉字
      - 第二个值是汉字
      - 第一个值是英文字母
      - 第二个值是英文字母
      - 第一个值是特殊字符*&
      - 第二个值是特殊字符@
  P2:
    datas:
      - [None, 20.93, "TypeError"]
      - [-3, None, "TypeError"]
      - [" ", 3.14, "TypeError"]
      - [-90, " ", "TypeError"]
    ids:
      - 第一个值None
      - 第二个值None
      - 第一个值空格
      - 第二个值空格

实战练习 2

  • 搜集执行失败用例信息:
    • 判断用例执行失败。
    • 提取失败用例信息。
  • 失败用例信息保存到 yaml 文件中。
# conftest.py
@pytest.hookimpl(hookwrapper=True, tryfirst=True)
def pytest_runtest_makereport(item, call):
    # 获取钩子方法的调用结果
    out = yield
    # 从钩子方法的调用结果中获取测试报告
    report = out.get_result()
    fail_case_info = []
    # 如果用例执行不通过
    if report.outcome != "passed":
        case_info = {
            "nodeid": report.nodeid,
            "result": report.outcome
        }
        fail_case_info.append(case_info)
        # 用例信息写入 yaml 文件
        with open('./fail_cases_info.yaml', 'a', encoding='utf-8') as f:
            yaml.dump(fail_case_info, f)

总结

  • 知识点:
    • 测试装置
    • 参数化
    • 命令行执行
    • 数据驱动
    • Pytest 内置插件