“python -m doctest”忽略不同目录中具有相同名称的文件

时间:2017-04-18 03:52:59

标签: python python-import doctest

假设我们有两个文件:

失败/ stuff.py

"""
>>> True
False
"""

PASS / stuff.py

"""
>>> True
True
"""

然后我们在doctest下运行它们:

python -m doctest fail/stuff.py pass/stuff.py

正如预期的那样,我们发现来自fail/stuff.py的错误。但如果我们以相反的顺序运行它们:

python -m doctest pass/stuff.py fail/stuff.py

然后它过去了!

为什么Python的导入系统无法应对来自两个文件的加载测试,还是doctest被破坏了?

2 个答案:

答案 0 :(得分:2)

在Python进程中只能有一个具有相同名称的顶级模块,python -m doctest将传递给它的所有文件视为顶级模块。导入pass/stuff.py将填充stuff模块的模块高速缓存中的条目,当doctest尝试导入您指定的第二个文件时,导入系统会查找pass/stuff.py的条目而不是加载{ {1}}。

他们可以尝试解决这个问题。例如,可以从文件中导入模块而不填写其fail/stuff.py条目,但如果这些具有相同名称的相同文件也具有相同名称,不同的依赖关系,或者如果有的话,这可能仍会失败涉及循环进口。他们可以尝试在运行测试后将sys.modules回滚到测试前的状态,这将更可靠但效率更低,并且仍然可能因为重新加载不能很好地运行的模块而失败。另一个选择是为每个测试生成一个单独的子进程,这将是最可靠但效率最低的。

答案 1 :(得分:2)

  

为什么Python的导入系统无法应对来自两个文件的加载测试,还是doctest被破坏了?

Doctests基本上就是破了。 Python导入系统无法处理这种情况的根本原因。因此,测试运行员无法处理这种情况也没有根本原因。我怀疑他们在编写命令行界面时是否过多考虑,因为大多数人不会直接使用doctest作为跑步者(而是将库代码与更全功能的跑步者整合并使用doctest插件会更常见)。

你可以使用更好的测试跑步者。例如,鼻子(以及其他人)不会遇到这个问题:

$ nosetests pass/stuff.py fail/stuff.py --with-doctest
.F
======================================================================
FAIL: Doctest: stuff
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/doctest.py", line 2199, in runTest
    raise self.failureException(self.format_failure(new.getvalue()))
AssertionError: Failed doctest test for stuff
  File "/private/tmp/fail/stuff.py", line 0, in stuff

----------------------------------------------------------------------
File "/private/tmp/fail/stuff.py", line 2, in stuff
Failed example:
    True
Expected:
    False
Got:
    True


----------------------------------------------------------------------
Ran 2 tests in 0.004s

FAILED (failures=1)