Python单元测试模块导入失败问题求助
Python unittest 测试文件导入问题
我是Python新手,写unittest时碰到了测试文件的导入问题。
文件夹结构
toyProjects └── pythonProj ├── mainpack │ ├── __init__.py │ ├── MyClass.py │ └── setup.py └── tests ├── __init__.py └── test_MyClass.py
另外pythonProj目录下还有一个mainfile.py(未在结构里展示),运行正常能找到所有文件,代码见下文。
各文件代码
MyClass.py
class MyClass: def __init__(self, x): self.x = x def someMethod(self): print("Called MyClass.someMethod");
setup.py
def myFunction(): print("Called setup.myFunction");
test_MyClass.py 初始代码
import unittest import setup from MyClass import MyClass class TestMyClass(unittest.TestCase): @classmethod def setUpClass(cls): cls.my = MyClass(4); def test_something(self): self.my.someMethod(); setup.myFunction();
mainfile.py
from mainpack import setup from mainpack.MyClass import MyClass print("Program start"); setup.myFunction() myInst = MyClass(4); myInst.someMethod();
测试运行命令
我用下面的命令运行测试:
cd toyProjects\pythonProj\tests python -m unittest test_MyClass.py
尝试过的导入方式及报错
我试了多种导入写法,都报错:
import setup→ModuleNotFoundError: No module named 'setup'from MyClass import MyClass→ModuleNotFoundError: No module named 'MyClass'from mainpack import setup→ModuleNotFoundError: No module named 'mainpack'from ..mainpack import setup→Unresolved reference mainpackimport mainpack→ModuleNotFoundError: No module named 'mainpack'from mainpack.setup import someFunction→Unresolved reference mainpackfrom .. import mainpack→ImportError: attempted relative import with no known parent package
我查过相关资料,知道修改sys.path通常不是规范做法,希望学习正确的解决方式;如果实在没办法,也可以接受修改sys.path,但之前试的修改都没效果。
解决方案
方法1:从项目根目录运行测试(最规范)
不要进入tests目录,直接在pythonProj目录下运行测试命令:
cd toyProjects\pythonProj python -m unittest tests/test_MyClass.py
然后修改test_MyClass.py里的导入语句,和mainfile.py保持一致:
import unittest from mainpack import setup from mainpack.MyClass import MyClass class TestMyClass(unittest.TestCase): @classmethod def setUpClass(cls): cls.my = MyClass(4); def test_something(self): self.my.someMethod(); setup.myFunction();
这种方式完全符合Python的包导入规范,不需要修改任何路径,因为项目根目录pythonProj会被加入Python的模块搜索路径,mainpack作为顶层包可以直接被导入。
方法2:使用相对导入(需保证测试包被正确识别)
如果一定要在tests目录下运行测试,需要把tests也当作一个包,并且确保Python能识别到它的父包。不过这种方式需要调整运行方式:
- 修改
test_MyClass.py的导入为相对导入:
import unittest from ..mainpack import setup from ..mainpack.MyClass import MyClass class TestMyClass(unittest.TestCase): @classmethod def setUpClass(cls): cls.my = MyClass(4); def test_something(self): self.my.someMethod(); setup.myFunction();
- 从
pythonProj目录下用包的方式运行测试:
cd toyProjects\pythonProj python -m unittest tests.test_MyClass
注意不能直接在tests目录下运行,否则Python无法识别..对应的父包。
方法3:临时修改sys.path(不推荐但可行)
如果上面两种方式都没法用,可以在test_MyClass.py开头添加代码,把项目根目录加入sys.path:
import unittest import sys from pathlib import Path # 获取项目根目录(pythonProj)的路径 project_root = Path(__file__).parent.parent sys.path.append(str(project_root)) from mainpack import setup from mainpack.MyClass import MyClass # 后续测试代码不变 class TestMyClass(unittest.TestCase): @classmethod def setUpClass(cls): cls.my = MyClass(4); def test_something(self): self.my.someMethod(); setup.myFunction();
然后可以继续在tests目录下用原来的命令运行测试。不过这种方式属于临时 hack,长期维护的话推荐用前两种规范方式。
内容的提问来源于stack exchange,提问作者MJL
相关产品推荐
相关产品推荐

