Python单元测试导入本地模块失败,ModuleNotFoundError问题求助
这问题我之前也碰到过!核心原因就是Python运行测试时的路径和作为包运行时的路径不一样——当你作为包运行时,src目录可能已经在Python的路径里了,但直接跑测试脚本时,Python默认的路径是测试文件所在的目录(也就是tests/),根本找不到src/app这个结构,所以才会报ModuleNotFoundError。给你几个靠谱的解决办法,都能兼顾包正常运行和测试通过:
办法一:手动把src目录加到Python路径
这个是最直接的临时解决方案,不用改任何代码。你可以在运行测试前,把项目根目录下的src文件夹添加到Python的环境变量PYTHONPATH里:
- 如果你用Unix/Linux/macOS,在终端里先执行:
然后再运行测试命令(比如export PYTHONPATH=/你的项目绝对路径/src:$PYTHONPATHpython -m unittest tests/test_function.py) - 如果你用Windows的cmd,先执行:
再跑测试set PYTHONPATH=C:\你的项目绝对路径\src;%PYTHONPATH%
如果你不想每次手动设环境变量,也可以在测试文件test_function.py的最顶部加一段代码,自动把src目录加到路径里:
import sys from pathlib import Path # 获取当前测试文件的父目录的父目录(也就是项目根目录),然后拼接src路径 sys.path.append(str(Path(__file__).parent.parent / "src")) # 下面是原来的测试代码 import unittest from src.app.file1 import function class TestFunction(unittest.TestCase): def test_case(self): self.assertTrue(function())
这样每次运行测试时,Python都会自动找到src目录,file1.py里的from app import file2就能正常导入了,包本身的代码也不用改。
办法二:改用相对导入
把file1.py里的导入语句改成相对导入,基于当前模块所在的包结构来导入:
# 把 from app import file2 改成下面这样 from . import file2 def function(): return file2.another_function()
这里的.表示当前模块所在的目录(也就是app包内部),这样不管是作为包运行,还是测试时导入,都能正确找到file2模块。不过要注意,这种相对导入只能在包内部使用,你不能直接把file1.py当成独立脚本运行(比如python src/app/file1.py),但如果你的项目本来就是作为包来使用的,这个限制完全没问题。
办法三:把包安装成可编辑模式(推荐长期项目用)
如果你的项目是一个打算正式维护的包,最好用这个方法。在项目根目录创建一个setup.py文件,内容如下:
from setuptools import setup, find_packages setup( name="your-app-name", # 改成你的包名 version="0.1", packages=find_packages(where="src"), package_dir={"": "src"}, # 告诉setuptools包的源码在src目录里 )
然后在项目根目录的终端里执行:
pip install -e .
这个命令会把你的包以“可编辑模式”安装到Python环境里,相当于给Python注册了你的包路径。之后不管是运行包本身,还是运行测试,导入路径都会自动正确识别,file1.py里的from app import file2完全不用改,两边都能正常工作。
备注:内容来源于stack exchange,提问作者RoyalSwish

