如何为无返回值的pytest fixture定义更精确的类型?
问题解答
测试参数中的mock_database在静态类型检查时标注为None,运行时实际值确实是None。但如果要区分SetupFixture和TeardownFixture这类不同职责的fixture类型,直接用None会导致类型无法区分,而用cast的取巧方案又必须返回值,不够优雅。以下是几种更合理的解决方案:
方案1:使用Literal标记类型
通过返回特定字面量值,让静态类型检查工具(如mypy)识别不同fixture的类型,运行时不影响测试逻辑(测试中无需使用该返回值):
from typing import Literal import pytest from _pytest.monkeypatch import MonkeyPatch # 定义不同的fixture类型标记 SetupFixture = Literal["mock_database_setup"] TeardownFixture = Literal["mock_database_teardown"] @pytest.fixture def mock_database_setup(monkeypatch: MonkeyPatch) -> SetupFixture: # 执行setup逻辑,比如修改数据库连接 monkeypatch.setattr("my_module.db.connect", lambda: None) # 返回标记值用于类型区分 yield "mock_database_setup" # 可选:执行teardown逻辑 @pytest.fixture def mock_database_teardown(monkeypatch: MonkeyPatch) -> TeardownFixture: # 执行setup逻辑 yield "mock_database_teardown" # 执行teardown逻辑,比如恢复原始连接 monkeypatch.undo() def test_with_setup(mock_database_setup: SetupFixture) -> None: # 静态类型检查会识别这是setup类型的fixture assert 1 == 1
方案2:使用空枚举类作为类型标记
用枚举单例作为类型标记,比字面量更结构化,运行时开销极小:
from enum import Enum import pytest from _pytest.monkeypatch import MonkeyPatch class SetupFixture(Enum): MARKER = None class TeardownFixture(Enum): MARKER = None @pytest.fixture def mock_database_setup(monkeypatch: MonkeyPatch) -> SetupFixture: monkeypatch.setattr("my_module.db.connect", lambda: None) yield SetupFixture.MARKER # 可选teardown逻辑 def test_with_setup(mock_database_setup: SetupFixture) -> None: # 类型检查明确区分该fixture的类型 ...
方案3:使用NewType包装None
通过NewType创建专属类型,静态检查时与普通None区分,运行时本质还是None:
from typing import NewType import pytest from _pytest.monkeypatch import MonkeyPatch SetupFixture = NewType("SetupFixture", None) TeardownFixture = NewType("TeardownFixture", None) @pytest.fixture def mock_database_setup(monkeypatch: MonkeyPatch) -> SetupFixture: monkeypatch.setattr("my_module.db.connect", lambda: None) # 用NewType包装None,仅用于类型标记 yield SetupFixture(None) def test_with_setup(mock_database_setup: SetupFixture) -> None: # 静态类型检查会将其识别为SetupFixture类型,而非普通None ...
以上方案均无需使用cast的取巧方式,既满足了类型区分的需求,又保持了代码的规范性和可读性。
内容的提问来源于stack exchange,提问作者komodovaran_
相关产品推荐
相关产品推荐

