Python 确保py.test在sys.path中包含应用程序目录
我有一个项目目录结构,如下所示(我认为这是相当标准的): 我正在使用py.test作为我的测试框架,我希望在Python 确保py.test在sys.path中包含应用程序目录,python,unit-testing,pytest,Python,Unit Testing,Pytest,我有一个项目目录结构,如下所示(我认为这是相当标准的): 我正在使用py.test作为我的测试框架,我希望在my_project目录中运行测试时能够运行py.tests。这确实有效,直到我尝试在测试中使用(例如)import mypkg导入我的应用程序代码。在这一点上,我得到了错误“没有名为mypkg的模块”。在进行一点调查后,似乎py.test使用sys.path中的测试文件目录运行测试,但不是运行py.test的目录 为了解决这个问题,我在tests目录中添加了一个conftest.py文件
my_project
目录中运行测试时能够运行py.tests
。这确实有效,直到我尝试在测试中使用(例如)import mypkg
导入我的应用程序代码。在这一点上,我得到了错误“没有名为mypkg的模块”。在进行一点调查后,似乎py.test
使用sys.path
中的测试文件目录运行测试,但不是运行py.test
的目录
为了解决这个问题,我在tests
目录中添加了一个conftest.py
文件,其中包含以下代码:
import sys, os
# Make sure that the application source directory (this directory's parent) is
# on sys.path.
here = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, here)
这似乎是可行的,但这是确保测试看到应用程序代码的好方法吗?有没有更好的方法来实现这一点,或者我的项目结构有问题吗
我看过其他一些使用py.test
(例如,pip
)的项目,但我看不到这样做的代码,而且运行py.test测试似乎在那里工作。我不知道为什么,但我担心他们可能会以更简单的方式取得同样的结果
我已经查看了py.test的documentation,但是我看不到关于这个问题的解释,也看不到处理这个问题的推荐方法。正如您所说的那样,py.test基本上假设您正确设置了PYTHONPATH。有几种方法可以实现这一点:
- 为您的项目提供一个setup.py,并在此项目的虚拟环境中使用
pip install-e.
。这可能是标准方法
- 如果您有一个virtualenv但没有setup.py,则使用venv的工具在sys.path上添加项目目录,例如,如果您使用pew,则使用pew add.
;如果您使用virtualenv和VirtualEnvrapper的扩展,则使用add2virtualenv.
如果您总是喜欢sys.path上的当前工作目录,您只需在shell中导出PYTHONPATH='
。这就是确保sys.path上的空字符串,python将其解释为当前工作目录。但这可能会造成安全隐患
我自己最喜欢的黑客,滥用py.test加载conftest文件的方式:在项目的顶级目录中放置一个空的conftest.py
py.test以这种方式运行的原因是,可以很容易地针对安装的包在签出的tests/目录中运行测试。如果它将无条件地将项目目录添加到PYTHONPATH,那么这将不再可能了。答案实际上要简单得多,如图所示
您所需要做的就是向测试目录及其每个子目录添加一个\uuuu init\uuuu.py
,如下所示
tests/__init__.py
tests/functional/__init__.py
tests/unit/__init__.py
简单的方法是,在terminal/cmd中将目录更改为父目录所在的位置(例如,在本例中,cd C:/…/my_project
)
然后运行:
python-mpytest--cov=mypkg测试
无需处理PYTHONPATH
环境变量。
通过使用python-m pytest运行,它会自动将当前目录添加到引用单个/多个包的sys.path
运行pytest
一包
PYTHONPATH=$(pwd)/mypkg/python3-m pytest
#或
PYTHONPATH=$(pwd)/mypkg/python3-m pytest路径/to/tests
适用于2个包装(pkg1 pkg2)
只是补充一点:如果你没有virtualenv,你可以使用“python setup.py develope”来达到同样的效果。conftest.py hack是个好主意!!!太糟糕了,这是一种虐待,看来它可能会消失:(安装一些东西来运行测试???使用更多的工具只是为了让测试运行程序工作???操纵Python路径,这是从来不推荐的,并且在项目中移动某些东西时必须再次进行更改???--不!添加一个空文件似乎是最简单的解决方案!我不知道为什么它能工作,但我很高兴它能工作。其他选项似乎完全错了,直到有人向我解释为什么我需要安装一些东西来测试它,而我已经有了所有的代码。@PascalVKooten最近讨论了为什么这个conftest.py
hack“有效”,以及为什么pytest
不“撤销”这是导入后的sys.path
修改。@Zelphir至于为什么要先安装一些东西来测试它,那么,你可以把它看作也是测试安装程序本身的一种方法。没有这一步,完全有可能有一个通过测试的套件,却有一个坏掉的安装程序(最终您意外地发布了一个损坏的包)。这实际上是在包中添加了测试。这可能并不总是需要的。-1因为在@BrianBruggeman中明确不鼓励这样做,我认为packages=find_包(exclude=['contrib','docs','tests'])
在setup.py中解决了这个问题?@wim,doc现在提供了两种方案-在应用程序包内部或外部进行测试,所以我认为这现在是一个有效的选项,在实践中,@alensijak仍然鼓励使用/tests
,并且不鼓励在代码结构中使用tests
文件夹。仍然存在不一致的问题使用pytest的一些插件(我主要使用coverage、isort和flake8)执行ent行为.这就是说,我已经开始将单元测试放在代码库的tests
文件夹中,将集成/系统级测试放在top/tests文件夹中,这对我来说很好。+1这是一个合法且有文档记录的功能,而不仅仅是一个意外。请参阅
tests/__init__.py
tests/functional/__init__.py
tests/unit/__init__.py
# Use ; as a separator in windows
PYTHONPATH=/path/to/pkg1/:/path/to/pkg2/ python3 -m pytest tests