我正在尝试通过将测试放在与我的应用程序不同的目录中来合理地组织我的代码。但是,导入为应用程序或执行 ,但不能同时执行这两项操作。这是一个人为的例子,说明了我目前的问题:
myapp/
app/
main.py
settings.py
moods.py
test/
test_moods.py
文件内容如下:
main.py
import settings
from moods import Moods
words = Moods(settings.EXAMPLE)
print(words.excited())
settings.py
EXAMPLE = "Wow$ Python$"
DELIM = "$"
moods.py
import settings
class Moods:
def __init__(self, text):
self.text = text
def excited(self):
return self.text.replace(settings.DELIM, "!!!")
test_moods.py
import sys, os, unittest
sys.path.insert(0, os.path.abspath('..'))
from app.moods import Moods
class TestMood(unittest.TestCase):
def setUp(self):
self.words = Moods("Broken imports$ So sad$")
def test_mood(self):
self.assertEqual(self.words.excited(), "Broken imports!!! So sad!!!")
with self.assertRaises(AttributeError):
self.words.angry()
if __name__ == "__main__":
unittest.main()
在当前状态下,从myapp/
我可以成功运行以下命令:
>> python3 app/main.py
Wow!!! Python!!!
但是当我尝试运行测试时,在moods.py中导入失败:
>> python3 -m unittest discover test/
ImportError: Failed to import test module: test_moods
[ stack trace here pointing to first line of moods.py ]
ImportError: No module named 'settings'
如果我将moods.py的第1行修改为from app import settings
,则测试将通过,但应用程序的正常执行会失败,因为它看不到模块app
。
我能想到的唯一解决方案是
sys.path.insert(0, os.path.abspath('..'))
添加到我的应用中的每个文件,以使导入的工作与测试的相同(这看起来很混乱)是否有更优雅的方法来解决这个导入问题?
答案 0 :(得分:2)
您应该在app
中同时拥有test
和PYTHONPATH
目录。
一种方法是替换它:
sys.path.insert(0, os.path.abspath('..'))
from app.moods import Moods
用这个:
sys.path.insert(0, os.path.abspath('../app'))
from moods import Moods
或者您可以在运行测试之前设置PYTHONPATH
environament变量。
为什么呢?因为当您运行main.py
时,app
位于路径中,而不是app/..
,因此您希望在运行测试时保持相同。