ImportError 显示为 py.test,但在 运行 应用程序时不显示

ImportError shows up with py.test, but not when running the app

不同于这个问题: 我可以从我的应用程序导入一些东西,但是 'inside' myapp 而 运行 引发了导入错误(看起来像循环依赖)测试而不是当 运行 myapp 单独时:

$ python3 myapp/myapp.py
Some dummy string (correct output)

但是:

$ python3 -m pytest                                                                               
================================================================= test session starts =================================================================
platform linux -- Python 3.4.3, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
rootdir: /home/nico/temp/projects_structures/test04/myapp, inifile: 
plugins: cov-2.2.1
collected 0 items / 1 errors 

======================================================================= ERRORS ========================================================================
________________________________________________________ ERROR collecting tests/test_things.py ________________________________________________________
tests/test_things.py:4: in <module>
    from myapp.lib.core.base import do_things
myapp/lib/core/base.py:1: in <module>
    from lib import something
E   ImportError: No module named 'lib'
=============================================================== 1 error in 0.05 seconds ===============================================================

如您所见,问题是 而不是 测试文件中的 import 语句。它来自 'inside' myapp.

完整结构如下:

.
└── myapp
    ├── myapp
    │   ├── __init__.py
    │   ├── lib
    │   │   ├── core
    │   │   │   ├── base.py
    │   │   │   └── __init__.py
    │   │   └── __init__.py
    │   └── myapp.py
    └── tests
        └── test_things.py

myapp.py 包含:

#!/usr/bin/env python3

from lib.core import base

base.do_things()

lib/__init__.py 包含:

something = "Some dummy string (correct output)"

base.py 包含:

from lib import something

def do_things():
    print(something)
    return True

和test_things包含:

import unittest
import sys
sys.path.insert(0, '..')
from myapp.lib.core.base import do_things

class DoThingsTestCase(unittest.TestCase):

    def test_do_things(self):
        self.assertTrue(do_things())

if __name__ == '__main__':
    unittest.main()

并且 $PYTHONPATH 似乎设置正确(因此: Py.test No module named * 没有回答我的问题)。 (或者如果这不正确,我该如何更正?)

$ echo $PYTHONPATH
/home/nico/temp/projects_structures/test04/myapp/myapp

设置 PYTHONPATH 应该可以解决问题。

$ export PYTHONPATH=<ABSOLUTE PATH TO TOPMOST myapp dir>

(在此示例中,它是 myapp/myapp 的路径;并确保您已 导出 PYTHONPATH,而不仅仅是设置它)。

来自 myapp 运行

$ py.test

$ python3 -m pytest

另一种方法是将 conftest.py 文件放入 myappmyapp/tests 的顶层。像这样:

$ pwd
/home/nico/temp/projects_structures/test04/myapp/tests
$ touch conftest.py
$ cd ..
$ py.test
================================================================= test session starts =================================================================
platform linux2 -- Python 2.7.6, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
rootdir: /home/nico/temp/projects_structures/test04/myapp, inifile: 
collected 1 items 

tests/test_things.py .

============================================================== 1 passed in 0.05 seconds ===============================================================
$

(并且 PYTHONPATH 为空:

$ echo $PYTHONPATH

$

)

这样,py.test 会自动将 myapp 添加到 PYTHONPATH。这避免了忘记导出 PYTHONPATH 并使 myapp 的测试对其他开发者来说更​​容易(他们都不需要解决这个问题)。