更改pytest rootdir

时间:2017-03-24 09:53:54

标签: import pytest

我被这个令人难以置信的愚蠢错误所困扰。我试图使用bluepy在Raspberry Pi上运行pytest。

pi@pi:~/bluepy/bluepy $ pytest test_asdf.py
============================= test session starts       ==============================
platform linux2 -- Python 2.7.9, pytest-3.0.7, py-1.4.33, pluggy-0.4.0
rootdir: /home/pi/bluepy, inifile:
collected 0 items / 1 errors

==================================== ERRORS ====================================
 ______________ ERROR collecting bluepy/test_bluetoothutility.py _______________
ImportError while importing test module '/home/pi/bluepy/bluepy/test_asdf.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
test_asdf:4: in <module>
    from asdf import AsDf
asdf.py:2: in <module>
    from bluepy.btle import *
E       ImportError: No module named btle
!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!
=========================== 1 error in 0.65 seconds ============================

我意识到我的问题可能是rootdir显示的路径不正确。它应该是

/home/pi/bluepy/bluepy

我一直在阅读pytest docs,但我不知道如何更改rootdir。

3 个答案:

答案 0 :(得分:3)

你的问题与Pytest的rootdir无关。

Pytest中的rootdir与how test package names are constructed没有关联,rootdir没有添加到sys.path,正如您从遇到的问题中可以看到的那样。 (注意:由于其他原因,可能会将被视为rootdir的目录添加到路径中,例如,当您运行python -m pytest时,它也是当前工作目录。)

正如其他人所描述的那样,此处的问题是顶级bluepy/不在sys.path中。如果你只想让自己以交互方式运行的话,最简单的处理方法是Cecil Curry's answercd到顶级bluepy并运行Pytest为python -m pytest bluepy/test_asdf.py (如果您希望它发现当前目录中或下的所有python -m pytest文件并运行它们,则只需test_*。但我认为您需要使用python -m pytest,而不仅仅是pytest,以确保当前工作目录位于路径中。

如果您正在设置一个其他人可以轻松运行的测试框架而没有像这样的神秘故障,您将需要设置一个测试脚本来设置当前工作目录或PYTHONPATH或其他适当的。或者使用tox。或者使用可以为您运行测试的标准工具将其设为Python包。 (这一切都超出了这个问题的范围。)

顺便说一句,我同意塞西尔对Mackie Messer's answer的看法;与conftest.py混在一起是非常困难和脆弱的;对于几乎任何情况都有更好的解决方案。

附录:使用rootdir

据我所知,只有两件事使用了rootdir:

  1. .pytest_cache/目录存储在rootdir中,除非另有说明(使用cache_dir配置选项)。
  2. 如果rootdir包含conftest.py,它将always be loaded,即使没有从rootdir中或下加载测试文件。
  3. documentation声称rootdir也用于生成nodeids,但添加了conftest.py包含

    def pytest_runtest_logstart(nodeid, location):
        print("logstart nodeid={} location={}".format(nodeid, location))            
    

    并且运行pytest --rootdir=/somewhere/way/outside/the/tree表明这是不正确的(尽管节点位置是相对于rootdir的。)

答案 1 :(得分:1)

我的第一个猜测是你在python路径中没有该目录。您可以动态地将它添加到python路径。一种简单的方法是在测试配置文件conftest.py中,我相信它总是在测试发现和测试运行之前执行。

例如,您可能有一个项目设置:

root
+-- tests
|   +-- conftest.py
|   +-- tests_asdf.py
+-- bluepy (or main project dir)
|   +-- miscellaneous modules

在这种情况下,您可以将根目录添加到conftest.py文件中的python路径,如下所示:

#
# conftest.py
import sys
from os.path import dirname as d
from os.path import abspath, join
root_dir = d(d(abspath(__file__)))
sys.path.append(root_dir)

如果有帮助,请告诉我。

答案 2 :(得分:1)

实际上,py.test 正确地发现您的项目的rootdir/home/pi/bluepy。那很好。

可悲的是,您错误地尝试在项目的包子目录(即py.test)内运行/home/pi/bluepy/bluepy,而不是在项目的rootdir内(即/home/pi/bluepy)。那很糟糕。

让我们稍微分解一下。来自:

  • /home/pi/bluepy目录,有一个bluepy.btle子模块。的好。
  • /home/pi/bluepy/bluepy子目录,有 no bluepy.btle子模块。 Bad。除非您笨拙地尝试将此子目录的父目录(即/home/pi/bluepy)手动注入sys.path {{3}也许Makie Messer,Python无法推断包bluepy实际上是指当前目录,同时也称为bluepy。为避免此类歧义问题,Python通常只在外部运行,而不是在项目的package子目录中运行

由于您从后者运行py.test而不是以前的目录,因此Python无法在当前bluepy.btle上找到sys.path子模块。出于这个原因和类似原因,py.test通常只应 从项目的顶级rootdir(即/home/pi/bluepy)运行

pi@pi:~/ $ cd ~/bluepy pi@pi:~/bluepy $ py.test bluepy/test_asdf.py

最后,请注意,将测试发现推迟到py.test通常更为可取。而不是在命令行上显式列出所有测试脚本文件名,而是考虑让py.test通过-k选项隐式查找并运行包含某些子字符串的所有测试。例如,要运行函数名称前缀为test_asdf的所有测试(无论它们驻留在哪个测试脚本中):

pi@pi:~/ $ cd ~/bluepy pi@pi:~/bluepy $ py.test -k test_asdf .

后缀.是可选的,但通常很有用。它指示py.test将其rootdir属性设置为当前目录(即/home/pi/bluepy)。 py.test 通常能够找到您的项目的rootdir并自行设置此属性,但手动指定它并不会有什么坏处。 (特别是当你有...... 问题。

有关rootdir发现的详细信息,请参阅inadvisably advises中的Initialization: determining rootdir and inifile