导入含交互式输入的setup.py导致单元测试失败的问题求助
解决方案:避免导入setup.py时执行交互式输入
这个问题我之前也碰到过——Python导入模块时会执行模块里的所有顶层代码,而你的setup.py里的交互式输入正好在顶层,加上pytest运行时会捕获标准输入输出,直接就撞出了OSError: reading from stdin while output is captured错误。给你几个实用的解决方案:
1. 把配置逻辑封装成函数,仅在直接运行时执行
把setup.py里的路径配置代码放到函数中,只有当直接运行setup.py时才触发交互式输入,导入时只加载函数,由调用方决定是否执行(测试时直接传默认路径)。
修改后的setup.py:
import os import sys def setup_test_path(test_folder_name=None): # 如果没有传入路径,才触发交互式输入 if test_folder_name is None: test_folder_name = input("Enter the name of the folder containing your tests:") test_folder_path = os.path.abspath(os.path.join(os.path.dirname(__file__), test_folder_name)) if os.path.exists(test_folder_path): sys.path.insert(0, test_folder_path) # 只有直接运行setup.py时才执行配置 if __name__ == "__main__": setup_test_path()
然后在testExemple.py中,手动调用函数并传入测试文件夹路径,跳过交互式输入:
from setup import setup_test_path # 测试环境下直接指定测试文件夹路径 setup_test_path(test_folder_name="./Test") # 接下来编写你的测试代码 class TestExample: def testAdd(self): # ... 测试逻辑
2. 用命令行参数/配置文件替代交互式输入
如果你的项目需要更灵活的配置,可以用命令行参数或者配置文件来传递路径,完全避免交互式输入。
比如用argparse处理命令行参数的setup.py:
import os import sys import argparse def setup_test_path(test_folder_name): test_folder_path = os.path.abspath(os.path.join(os.path.dirname(__file__), test_folder_name)) if os.path.exists(test_folder_path): sys.path.insert(0, test_folder_path) if __name__ == "__main__": parser = argparse.ArgumentParser(description="Setup project paths") parser.add_argument("--test-folder", required=True, help="Path to the test folder") args = parser.parse_args() setup_test_path(args.test_folder)
运行时用命令行传参:python setup.py --test-folder ./Test,测试时同样直接调用setup_test_path传入路径即可。
3. 自动检测测试环境,跳过交互式输入
可以通过检测sys.modules中是否包含pytest来判断是否在测试环境中,自动切换到默认路径:
修改后的setup.py:
import os import sys def is_running_pytest(): # 检查是否在pytest环境中 return "pytest" in sys.modules def setup_test_path(): if is_running_pytest(): # 测试环境,使用预设的默认路径 test_folder_name = "./Test" else: # 正常运行时触发交互式输入 test_folder_name = input("Enter the name of the folder containing your tests:") test_folder_path = os.path.abspath(os.path.join(os.path.dirname(__file__), test_folder_name)) if os.path.exists(test_folder_path): sys.path.insert(0, test_folder_path) if __name__ == "__main__": setup_test_path()
这样导入setup.py时,如果是pytest在运行,会自动使用默认路径,不会弹出输入提示,完美解决测试时的stdin错误。
内容的提问来源于stack exchange,提问作者user8584384
相关产品推荐
相关产品推荐

