Running a python script with nose.run(...) from outside of the script's directory results in AttributeError: 'module' object has no attribute 'tests'

Running a python script with nose.run(...) from outside of the script's directory results in AttributeError: 'module' object has no attribute 'tests'

我有一个带有几个子目录的 python 应用程序。每个子目录都有自己的 tests.py 文件。

我使用 nose 运行 通过创建一个调用 nose.run(...).

的脚本 run_unit_tests.py 一次性对所有这些文件进行所有单元测试

如果我在包含 run_unit_tests.py 的目录中,一切正常。但是,如果我在文件系统的其他任何地方,它会失败并显示 AttributeError: 'module' object has no attribute 'tests'.

这是类似于我的目录结构的内容:

MyApp/
    foo/
        __init__.py
        tests.py
        bar/
            __init__.py
            tests.py
    run_unit_tests.py

在我的 run_unit_tests.py:

class MyPlugin(Plugin):
    ...

if __name__ == '__main__':
    nose.run(argv=['', 'foo.tests', '--with-my-plugin'])
    nose.run(argv=['', 'foo.bar.tests', '--with-my-plugin'])

如果我 运行 run_unit_tests.py 在顶级 MyApp 目录中,一切正常。

但是,如果我 运行 脚本在文件系统上的某个其他文件夹中时,它会失败:

======================================================================
ERROR: Failure: AttributeError ('module' object has no attribute 'tests')
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/apps/Python/lib/python2.7/site-packages/nose/loader.py", line 407, in loadTestsFromName
    module = resolve_name(addr.module)
  File "/apps/Python/lib/python2.7/site-packages/nose/util.py", line 322, in resolve_name
    obj = getattr(obj, part)
AttributeError: 'module' object has no attribute 'tests'

事实上,如果我将以下内容添加到 run_unit_tests.py,它工作正常:

import os
os.chdir('/path/to/MyApp')

我可以在我的 nose 脚本内部更改什么,以便我可以 运行 从目录外部的脚本?

其实你要小心这里。因为,发生这种情况的原因是因为您在测试中的导入是关于:/path/to/MyApp.

因此,当您 运行 从该工作目录进行测试时,您的单元测试文件都是相对于作为项目源的目录导入的。如果您从另一个位置更改目录和 运行,那现在成为您的根目录,并且您的导入肯定会失败。

这可能会带来不同的意见,但我通常会确保我的源代码都是从同一个项目根目录中引用的。所以如果我们在这里:

MyApp/
    foo/
        __init__.py
        tests.py
        bar/
            __init__.py
            tests.py
    run_unit_tests.py

我会 运行 MyApp

中的所有内容

此外,我会考虑创建一个 tests 目录并将所有测试放在该目录中,使您的导入更易于管理并更好地隔离代码。但是,这只是一个意见,请不要觉得这是必要的。不管对你有用什么,随它去吧。

希望这对您有所帮助。