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

如何在不重复代码的情况下为多模块运行相同的Pytest测试?

问题描述

我有一个包含多个模块的项目,这些模块普遍需要同类测试。每个模块都会导入同名文件,基于该文件的测试逻辑完全相同。

当前测试代码示例:

# test/integration/app1_test.py

from app1 import app

def test_app():
  response = app.get_response()
  assert response == True

app1、app2、app3的测试逻辑完全一致。我想避免在app1_test、app2_test、app3_test中重复编写相同代码,理想是通过继承类实现,比如:

test/conftest.py:

class TestApp:
  def __init__(self, App): # 希望能将其作为fixture传入
    self.app = App
  def test_app(self):
    response = self.app.get_response()
    assert response == True

test/integration/app1_test.py:

from app1 import app

@pytest.fixture(scope="module")
def App():
  return app

test/integration/app2_test.py:

from app2 import app
from conftest import TestApp

@pytest.fixture(scope="module")
def App():
  return app

class TestApp2(TestApp):
  def test_app(self):
    response = self.app.get_response()
    assert response == False
  def test_another_response(self):
    response = self.app.get_another_response()
    assert response == True

我能实现最接近上述流程的方案是什么?

我试过把测试函数放在conftest.py中,但执行python3 -m pytest时这些函数不会运行;也试过编写函数在各测试模块中导入手动运行,但它们不会被识别为pytest测试,只是普通Python函数。我希望pytest能收集并为项目中的每个模块运行这些测试。

可行解决方案

方法1:参数化fixture+共享测试函数(最简洁)

不需要类继承,直接通过参数化批量生成测试:

  1. 在test/conftest.py中定义参数化fixture和基础测试逻辑:
import pytest
from app1 import app as app1
from app2 import app as app2
from app3 import app as app3

# 为每个模块的app实例生成参数,ids用于区分测试用例
@pytest.fixture(params=[app1, app2, app3], ids=["app1", "app2", "app3"])
def app(request):
    return request.param

# 基础测试逻辑,会自动为每个app实例执行一次
def test_app_base_response(app):
    response = app.get_response()
    assert response == True

执行python3 -m pytest时,pytest会自动为app1、app2、app3各运行一次test_app_base_response,无需在每个测试文件重复编写代码。

方法2:类继承+fixture注入(贴合你的需求)

如果偏好类继承的方式,可以通过pytest的fixture注入实现:

  1. 在test/conftest.py定义基础测试类:
class BaseTestApp:
    # 测试方法依赖名为app的fixture,由子类所在模块提供
    def test_app_response(self, app):
        response = app.get_response()
        assert response == True
  1. 在各模块的测试文件中,定义本地app fixture并继承基础类:
# test/integration/app1_test.py
from app1 import app
from conftest import BaseTestApp
import pytest

@pytest.fixture(scope="module")
def app():
    return app

class TestApp1(BaseTestApp):
    # 直接继承基础测试方法,pytest会自动收集执行
    pass
# test/integration/app2_test.py
from app2 import app
from conftest import BaseTestApp
import pytest

@pytest.fixture(scope="module")
def app():
    return app

class TestApp2(BaseTestApp):
    # 重写基础测试,覆盖原有断言逻辑
    def test_app_response(self, app):
        response = app.get_response()
        assert response == False
    
    # 添加模块专属的测试方法
    def test_another_response(self, app):
        response = app.get_another_response()
        assert response == True

这种方式下,每个测试文件只需定义本地的app fixture,继承基础类后,pytest会自动收集并执行所有测试方法(包括继承的和自定义的)。

注意事项

  • conftest.py是用来共享fixture和钩子函数的,不能直接存放测试用例,否则pytest不会收集执行。
  • pytest只会识别测试模块(命名含test_)中,以test_开头的函数/方法,直接导入的普通函数不会被当作测试用例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 01:52:05