不同目录中的测试调用相同时测试发现失败

Posted

技术标签:

【中文标题】不同目录中的测试调用相同时测试发现失败【英文标题】:Test discovery failure when tests in different directories are called the same 【发布时间】:2012-09-16 22:39:33 【问题描述】:

使用 py.test,在不同目录中调用相同的两个测试会导致 py.test 失败。这是为什么?如何在不重命名所有测试的情况下更改它?

复制做:

; cd /var/tmp/my_test_module
; mkdir -p ook/test           
; mkdir -p eek/test
; touch ook/test/test_proxy.py
; touch eek/test/test_proxy.py
; py.test
============================= test session starts ==============================
platform linux2 -- Python 2.7.3 -- pytest-2.2.4
collected 0 items / 1 errors 

==================================== ERRORS ====================================
___________________ ERROR collecting ook/test/test_proxy.py ____________________
import file mismatch:
imported module 'test_proxy' has this __file__ attribute:
  /home/ygolanski/code/junk/python/mymodule/eek/test/test_proxy.py
which is not the same as the test file we want to collect:
  /home/ygolanski/code/junk/python/mymodule/ook/test/test_proxy.py
HINT: remove __pycache__ / .pyc files and/or use a unique basename for your test file modules
=========================== 1 error in 0.01 seconds ============================

【问题讨论】:

【参考方案1】:

输入__init__.py 是解决冲突的一种方法。与鼻子不同,当前的 pytest 不会尝试卸载测试模块以导入具有相同导入名称的测试模块。我曾经认为这种自动取消导入有点神奇,并且可能会扰乱人们对导入机制所做的期望;有时人们依赖于测试模块的全局状态,并且自动卸载会丢失它(从另一个测试模块导入的测试模块可能会做意想不到的事情)。但也许这不是一个实际问题,因此 pytest 可以添加类似的 hack ...

【讨论】:

我同意要求 init.py 是有道理的。如果测试不在包中,那么它本质上是一个***模块(在 OP 中,test_proxy)并且应该只有一个。通过将测试模块放在相关的包(ook 和 eek)中,它提供了正确的测试命名空间。我说现状是最好的。将错误消息链接到此问题或文档中解释解决该问题的推理和技术的内容可能会减轻一些痛苦。 请注意,py.test 文档特别建议不要将 __init__.py 放在测试目录中:"避免将 __init__.py 文件放在测试目录中。这样您的测试可以轻松地针对mypkg 的安装版本,独立于安装的包是否包含测试”。取自pytest.org - Good Integration Practices。 更新:@ Famousgarkin 上面的评论和答案 (***.com/a/21942491/260303) 中的建议似乎不再出现在文档中(至少搜索“avoid”不会出现上面的引用): docs.pytest.org/en/latest/…。实际上,该链接中的示例在测试目录中显示__init__.py,因此似乎接受的答案是正确的。 我从来没有完全理解过 pytest 测试发现逻辑。当我遇到发现错误时,我只是寻找放置__ini__.pys¯_(ツ)_/¯的地方。到目前为止一直为我工作。 @ Famousgarkin 在github.com/pytest-dev/pytest/pull/2297 中删除【参考方案2】:

这是 py.test 的一个实际功能。您可以在pytest.org - Good Integration Practices - Choosing a test layout / import rules 中找到这种行为的原因:

避免测试目录中的__init__.py 文件。这样,您的测试就可以轻松地针对已安装的 mypkg 版本运行,而与安装的软件包是否包含测试无关。

因为这是使用 py.test 的推荐工作流程:使用 pip install -e 安装正在开发的包,然后对其进行测试。

因此,我自己选择了唯一的测试名称,以约定优于配置的方式。它还确保您不会在各种测试运行输出中得到模棱两可的测试名称。

如果您需要保留测试名称并且不关心上述功能,您应该可以输入__init__.py

【讨论】:

我不明白用例:“这样您的测试可以轻松地针对已安装的 mypkg 版本运行”。我针对 mypkg 的开发版本运行测试。这样测试就存在了。我创建 __init__.py 文件以避免出现此“唯一基本名称”错误消息。 我创建了一个功能请求来更改文档:bitbucket.org/hpk42/pytest/issue/529/… @guettli 用例是当您想要测试通过 setup.py 安装的包时。这可用于确保您在安装中包含所有必需的文件,例如捆绑数据,并且所有依赖项都得到正确处理。它还可以用于安装在目标系统没有编译器的环境中,并且您将使用二进制鸡蛋或***进行安装。 链接中有错字。这是正确的链接:pytest.org/latest/…【参考方案3】:

我遇到了同样的错误,但解决方案与 init 文件或测试文件上的名称无关。我的 ma​​cbookDocker 容器上有不同的 python 版本。我从项目根目录的 macbook 的 bash 中启动了一次测试,而不是容器的 bash。

解决方案是通过运行(从容器的 bash 中)删除错误创建的文件:

find -name '*.pyc' -delete
find -name __pycache__ -delete

然后再次启动测试(仍然来自容器的 bash),一切正常:

py.test

【讨论】:

我在 docker 容器中遇到了同样的问题,这个答案救了我的命。我认为它应该被@hpk42 添加到接受的答案中。

以上是关于不同目录中的测试调用相同时测试发现失败的主要内容,如果未能解决你的问题,请参考以下文章

信号量等待导致 AFNetworking 阻塞?

使用 Jasmine 在 AngularJS 中测试去抖函数从不调用该函数

如何使用不同的地址来调用 Hardhat 测试和脚本中的函数?

UI 测试失败:发现多个匹配错误

Pytest02-用法和调用

是啥导致在单元测试(NUnit 或 MSTest)中从 C# 调用的 C++ 函数与在控制台应用程序中运行的相同代码产生不同的结果?