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

如何避免uv构建的Python包包含同文件内的测试函数?

如何在Python源码文件中内嵌单元测试且不导出测试函数(类似Rust #[cfg(test)])

我用uv和pyproject.toml管理Python包,希望像Rust的#[cfg(test)]那样,把单元测试和源码放在同一文件,tests/目录仅用于集成测试。目前在源码里直接写的测试函数会和业务函数一起被导出,示例代码如下:

# add.py
def add(a, b):
    return a + b

def test_add():
    assert add(1, 2) == 3

用uv run pytest能正常执行测试,但构建包后test_add会被模块导出,想解决这个问题。自己尝试过通过检查sys.modules是否包含"pytest"来条件定义测试函数,但觉得这种方式不够稳妥。

可靠的解决方案

方案1:基于sys.modules的条件判断(优化版)

你的思路本质是可行的,只需稍作优化就能提升可靠性。pytest运行时会提前加载自身模块,因此sys.modules中必然存在"pytest";而正常运行或构建包时,该模块不会被加载,测试函数也就不会被定义:

# add.py
import sys

def add(a, b):
    return a + b

# 仅在pytest运行环境下定义测试函数
if "pytest" in sys.modules:
    def test_add():
        assert add(1, 2) == 3

如果担心极端场景下的误判,可以结合命令行参数检查进一步增强严谨性:

import sys

def add(a, b):
    return a + b

# 同时检查pytest模块是否加载、命令行是否包含pytest相关参数
if "pytest" in sys.modules or any("pytest" in arg for arg in sys.argv):
    def test_add():
        assert add(1, 2) == 3

方案2:使用__test__字典隐藏测试函数

将测试函数定义为私有函数,再通过模块的__test__字典注册给pytest。这样测试函数不会成为模块的顶级导出成员,但pytest仍能正常识别并执行:

# add.py
def add(a, b):
    return a + b

# 用于注册测试用例的字典,pytest会自动识别
__test__ = {}

# 私有测试函数,不会被模块导出
def _test_add():
    assert add(1, 2) == 3

# 将私有测试函数注册到__test__字典
__test__["test_add"] = _test_add

验证效果

用uv build构建包后,安装并导入模块:

from foo import add

# 尝试访问test_add会抛出AttributeError
print(dir(add))  # 输出中不会包含test_add或_test_add

同时uv run pytest仍能正常发现并执行测试用例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 00:55:08