在py.test中,conftest.py文件有什么用处?
我最近发现了py.test
。 这似乎很棒。 不过,我觉得文件可能会更好。
我试图了解什么conftest.py
文件是用来作为。
在我的(目前很小的)testing套件中,我在项目根目录下有一个conftest.py
文件。 我用它来定义我注入到testing中的灯具。
我有两个问题:
- 这是
conftest.py
的正确使用吗? 它有其他用途吗? - 我可以有多个
conftest.py
文件吗? 我什么时候想要这样做? 例子将不胜感激。
更一般地说,你如何定义pytesttesting套件中conftest.py
文件的目的和正确使用?
这是conftest.py的正确使用吗?
是的,Fixtures是conftest.py
一个潜在和常见的用途。 您将定义的灯具将在testing套件中的所有testing中共享。 但是在conftest.py
根目录下定义灯具可能是没有用的,如果所有的testing都没有使用这样的灯具,它会减慢testing的速度。
它有其他用途吗?
是的,它确实。
-
夹具 :为testing使用的静态数据定义夹具。 这个数据可以被套件中的所有testing访问,除非被指定。 这可能是数据以及将传递给所有testing的模块的助手。
-
外部插件加载 :conftest.py用于导入外部插件或模块。 通过定义以下全局variables,pytest将加载模块并使其可用于其testing。 插件通常是在您的项目或其他模块中定义的文件,可能在您的testing中需要。 这里也可以加载一组预定义的插件。
pytest_plugins = "someapp.someplugin"
-
钩子 :你可以指定钩子,比如设置和拆卸方法等,以改善你的testing。 对于一组可用的钩子,请阅读这里 。 例:
def pytest_runtest_setup(item): """ called before ``pytest_runtest_call(item). """ #do some stuff`
-
testing根path :这是一个隐藏的function。 通过在你的根path中定义
conftest.py
,你可以在不指定PYTHONPATH
情况下通过pytest
识别你的应用程序模块。 在后台,py.test通过包含从根pathfind的所有子模块来修改你的sys.path
。
我可以有多个conftest.py文件吗?
是的,你可以和强烈build议,如果你的testing结构是复杂的。 conftest.py
文件具有目录范围,因此创build有针对性的装置和帮手是很好的做法。
我什么时候想要这样做? 例子将不胜感激。
有几种情况可以适用:
为特定的一组testing创build一组工具或挂钩
根/ MOD / conftest.py
def pytest_runtest_setup(item): print("I am mod") #do some stuff test root/mod2/test.py will NOT produce "I am mod"
为一些testing加载一套灯具 ,但不适用于其他灯具 。
根/ MOD / conftest.py
@pytest.fixture() def fixture(): return "some stuff"
根/ MOD2 / conftest.py
@pytest.fixture() def fixture(): return "some other stuff"
根/ MOD2 / test.py
def test(fixture): print(fixture)
将打印“一些其他的东西”
覆盖从根conftest.py
inheritance的conftest.py
根/ MOD / conftest.py
def pytest_runtest_setup(item): print("I am mod") #do some stuff
根/ conftest.py
def pytest_runtest_setup(item): print("I am root") #do some stuff
通过在root/mod
运行任何testing,只打印“我是mod”。
你可以在这里阅读更多关于conftest.py
。
编辑:
如果我需要简单的帮助函数从不同的模块中进行多个testing,那么如果我把它们放在conftest.py中,它们是否可用? 或者我应该把它们放在一个helpers.py模块中,然后导入并在我的testing模块中使用它?
你可以使用conftest.py
来定义你的助手,但你应该遵循惯例。 至less在py.test
助手可以作为灯具使用。 例如,在我的testing中,我有一个嘲笑的redis助手,我用这种方式注入到我的testing中。
根/辅助/ redis的/ redis.py
@pytest.fixture def mock_redis(): return MockRedis()
根/testing/材料/ conftest.py
pytest_plugin="helper.redis.redis"
根/testing/材料/ test.py
def test(mock_redis): print(mock_redis.get('stuff'))
这将是一个testing模块,您可以在testing中自由导入。 请注意 ,如果您的模块redis
包含更多testing,则可以将redis.py
为conftest.py
。 不过,这种做法因含糊不清而令人灰心。
如果你想使用conftest.py
你可以把这个助手放在你的根conftest.py中,并在需要的时候注入。
根/testing/ conftest.py
@pytest.fixture def mock_redis(): return MockRedis()
根/testing/材料/ test.py
def test(mock_redis): print(mock_redis.get(stuff))
你可以做的另一件事是写一个可安装的插件。 在这种情况下,你的助手可以在任何地方编写,但是它需要定义一个入口点来安装在你的潜在的testing框架中。 看到这个
如果你不想使用灯具,你当然可以定义一个简单的助手,只需要使用普通的旧导入。
根/testing器/辅助/ redis.py
class MockRedis(): # stuff
根/testing/材料/ test.py
from helper.redis import MockRedis def test(): print(MockRedis().get(stuff))
但是,在这里,您可能会遇到path问题,因为模块不在testing的子文件夹中。 你应该可以通过向你的帮手添加一个init来克服这个(未testing)
根/testing器/辅助/ __ init__.py
from .redis import MockRedis
或者简单地将辅助模块添加到您的PYTHONPATH
。
从广义上讲,conftest.py是一个本地的per-directory插件。 在这里你可以定义特定于目录的钩子和灯具。 在我的情况下,有一个根目录包含项目特定的testing目录。 一些常见的魔法是驻扎在“根”conftest.py。 项目具体 – 在他们自己的。 在conftest.py中存储灯具,除非它们没有被广泛使用,否则看不出什么坏东西(在这种情况下,我更喜欢直接在testing文件中定义它们)