You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

pytest中Mocha钩子等价实现及API测试数据初始化方案咨询

pytest 对应 Mocha 钩子的等价实现

Mocha 的四个核心钩子在 pytest 中有直接的等价实现,对应关系如下:

  • Mocha before → pytest setup_module 函数或 scope="module" 的 fixture
    • setup_module 是模块级前置逻辑,在当前 .py 文件所有测试用例执行前仅运行一次,适合初始化模块级共享资源。
      示例:
    def setup_module(module):
        # 模块级前置操作:比如加载全局配置、初始化API会话
        print("所有测试用例执行前运行一次")
    
  • Mocha beforeEach → pytest setup_function 函数或默认 scope="function" 的 fixture
    • setup_function 在每个测试函数执行前运行,适合初始化单个用例的专属数据。
      示例:
    def setup_function(func):
        # 用例级前置操作:比如创建临时测试数据
        print(f"测试用例 {func.__name__} 执行前运行")
    
  • Mocha after → pytest teardown_module 函数或 scope="module" 的 fixture(通过 yield 实现后置)
    • teardown_module 在模块所有用例执行完成后仅运行一次,用于清理模块级资源。
      示例:
    def teardown_module(module):
        # 模块级后置操作:比如关闭全局会话、清理共享数据
        print("所有测试用例执行后运行一次")
    
  • Mocha afterEach → pytest teardown_function 函数或默认 scope="function" 的 fixture(通过 yield 实现后置)
    • teardown_function 在每个测试函数执行完成后运行,用于清理单个用例的临时数据。
      示例:
    def teardown_function(func):
        # 用例级后置操作:比如删除临时测试数据
        print(f"测试用例 {func.__name__} 执行后运行")
    
API测试前置需求的解决方案

针对你需要的「模块执行前运行脚本」「每个测试用例前初始化测试数据」的需求,除了 fixture 外,还有以下实用方案:

1. 直接使用 setup/teardown 系列函数

这是最直观的方式,完全匹配你的需求场景:

  • 模块级前置:用 setup_module 做全局初始化(比如加载API配置、创建全局请求会话、获取全局token)
  • 用例级前置:用 setup_function 做单个用例的测试数据初始化(比如创建临时用户、生成专属测试资源)

示例代码:

import requests

# 模块级前置:初始化全局API会话
def setup_module(module):
    module.session = requests.Session()
    module.base_url = "https://api.example.com/v1"
    # 登录获取全局token
    login_res = module.session.post(f"{module.base_url}/login", json={"username": "test", "password": "123456"})
    module.session.headers["Authorization"] = f"Bearer {login_res.json()['token']}"

# 用例级前置:每个用例前创建临时测试用户
def setup_function(func):
    create_user_res = session.post(f"{base_url}/users", json={"name": "temp_user"})
    func.test_user_id = create_user_res.json()["id"]

# 测试用例
def test_get_user_detail():
    res = session.get(f"{base_url}/users/{test_get_user_detail.test_user_id}")
    assert res.status_code == 200
    assert res.json()["name"] == "temp_user"

2. 自定义测试基类(面向对象风格)

如果习惯用类组织测试用例,可以编写一个基类封装前置逻辑,测试类继承后直接复用:

示例代码:

import requests
import pytest

class BaseAPITest:
    session = None
    base_url = "https://api.example.com/v1"

    @classmethod
    def setup_class(cls):
        # 类级前置:所有类内测试用例执行前运行一次
        cls.session = requests.Session()
        login_res = cls.session.post(f"{cls.base_url}/login", json={"username": "test", "password": "123456"})
        cls.session.headers["Authorization"] = f"Bearer {login_res.json()['token']}"

    def setup_method(self):
        # 方法级前置:每个测试方法执行前运行
        create_user_res = self.session.post(f"{self.base_url}/users", json={"name": "temp_user"})
        self.test_user_id = create_user_res.json()["id"]

class TestUserAPI(BaseAPITest):
    def test_get_user(self):
        res = self.session.get(f"{self.base_url}/users/{self.test_user_id}")
        assert res.status_code == 200

    def test_delete_user(self):
        res = self.session.delete(f"{self.base_url}/users/{self.test_user_id}")
        assert res.status_code == 204

补充:Fixture 其实可以控制传入数据

你提到觉得 fixture 无法控制传入数据,其实可以通过工厂模式或参数化实现动态传参:

工厂模式 fixture(动态传入自定义数据)

import pytest
import requests

@pytest.fixture(scope="module")
def api_session():
    session = requests.Session()
    base_url = "https://api.example.com/v1"
    login_res = session.post(f"{base_url}/login", json={"username": "test", "password": "123456"})
    session.headers["Authorization"] = f"Bearer {login_res.json()['token']}"
    yield session

@pytest.fixture
def create_test_user(api_session):
    # 返回一个工厂函数,允许传入自定义参数
    def _create_user(name="temp_user"):
        res = api_session.post(f"{base_url}/users", json={"name": name})
        return res.json()["id"]
    return _create_user

# 测试用例中传入自定义用户名
def test_get_custom_user(create_test_user):
    user_id = create_test_user(name="my_custom_user")
    res = api_session.get(f"{base_url}/users/{user_id}")
    assert res.json()["name"] == "my_custom_user"

参数化 fixture(批量测试不同数据)

@pytest.fixture(params=["user1", "user2", "user3"])
def test_user_name(request):
    return request.param

def test_create_user(api_session, test_user_name):
    res = api_session.post(f"{base_url}/users", json={"name": test_user_name})
    assert res.json()["name"] == test_user_name

内容的提问来源于stack exchange,提问作者Mona101ma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 06:50:53