问题:在pytest中,conftest.py文件有什么用?
我最近发现了pytest
。好像很棒 但是,我认为文档可能会更好。
我正在尝试了解conftest.py
文件的用途。
在我的(目前很小的)测试套件conftest.py
中,项目根目录下有一个文件。我用它来定义要注入测试的灯具。
我有两个问题:
- 这是正确的用法
conftest.py
吗?它还有其他用途吗? - 我可以有多个
conftest.py
文件吗?我什么时候要这么做?示例将被理解。
更一般而言,您如何定义conftest.py
py.test测试套件中的目的和正确使用文件?
回答 0
这是conftest.py的正确用法吗?
是的。治具是潜在的和普遍的使用conftest.py
。您将定义的固定装置将在测试套件中的所有测试之间共享。但是,在根目录中定义固定装置conftest.py
可能没有用,如果所有测试未使用此类固定装置,则会减慢测试速度。
它还有其他用途吗?
是的,它确实。
夹具:为测试使用的静态数据定义夹具。除非另有说明,否则套件中的所有测试都可以访问此数据。这可能是数据以及将传递给所有测试的模块帮助程序。
外部插件加载:
conftest.py
用于导入外部插件或模块。通过定义以下全局变量,pytest将加载模块并使它可用于其测试。插件通常是在项目或测试中可能需要的其他模块中定义的文件。您还可以按照此处的说明加载一组预定义的插件。pytest_plugins = "someapp.someplugin"
挂钩:您可以指定挂钩(例如设置和拆卸方法)以及更多内容来改善测试。有关一组可用的挂钩,请阅读此处。例:
def pytest_runtest_setup(item): """ called before ``pytest_runtest_call(item). """ #do some stuff`
测试根路径:这是一个隐藏功能。通过
conftest.py
在根路径中进行定义,pytest
无需指定即可识别应用程序模块PYTHONPATH
。py.test在后台sys.path
通过包含从根路径找到的所有子模块来修改您的文件。
我可以有多个conftest.py文件吗?
是的,您可以,如果测试结构有些复杂,强烈建议您这样做。conftest.py
文件具有目录范围。因此,创建有针对性的装置和助手是一个好习惯。
我什么时候要这么做?示例将不胜感激。
几种情况可能适合:
为一组特定的测试创建一组工具或挂钩。
root / 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"
加载一组夹具用于某些测试,但不用于其他测试。
root / mod / conftest.py
@pytest.fixture()
def fixture():
return "some stuff"
root / mod2 / conftest.py
@pytest.fixture()
def fixture():
return "some other stuff"
root / mod2 / test.py
def test(fixture):
print(fixture)
将打印“其他一些东西”。
覆盖从根继承的钩子conftest.py
。
root / mod / conftest.py
def pytest_runtest_setup(item):
print("I am mod")
#do some stuff
root / conftest.py
def pytest_runtest_setup(item):
print("I am root")
#do some stuff
通过在内部运行任何测试root/mod
,仅打印“ I am mod”。
您可以conftest.py
在此处了解更多信息。
编辑:
如果我需要从不同模块中的多个测试中调用普通的辅助函数,该怎么办-如果将它们放在conftest.py中,它们将对我可用吗?还是我应该将它们放在helpers.py模块中,然后在测试模块中导入并使用它?
您可以conftest.py
用来定义您的助手。但是,您应该遵循常规做法。辅助工具至少可以在中用作固定装置pytest
。例如,在我的测试中,我有一个模拟的redis帮助器,可以通过这种方式将其注入到我的测试中。
根目录/helper/redis/redis.py
@pytest.fixture
def mock_redis():
return MockRedis()
根/测试/材料/ conftest.py
pytest_plugin="helper.redis.redis"
根/测试/材料/ test.py
def test(mock_redis):
print(mock_redis.get('stuff'))
这将是一个测试模块,您可以自由地将其导入测试中。注意,您可能会命名redis.py
,conftest.py
好像您的模块redis
包含更多测试一样。但是,由于模棱两可,不鼓励这种做法。
如果要使用conftest.py
,只需将该帮助程序放在根目录中conftest.py
,并在需要时将其注入。
root / tests / conftest.py
@pytest.fixture
def mock_redis():
return MockRedis()
根/测试/材料/ test.py
def test(mock_redis):
print(mock_redis.get(stuff))
您可以做的另一件事是编写一个可安装的插件。在那种情况下,您的助手可以写在任何地方,但是需要定义一个要安装在您的和其他潜在测试框架中的入口点。看到这个。
如果您不想使用固定装置,则当然可以定义一个简单的帮助器,并在需要的地方使用普通的旧导入。
root /测试/helper/redis.py
class MockRedis():
# stuff
根/测试/材料/ test.py
from helper.redis import MockRedis
def test():
print(MockRedis().get(stuff))
但是,由于模块不在测试的子文件夹中,因此此处可能存在路径问题。您应该能够克服这(未测试)通过添加__init__.py
到您的帮助
root / tests / helper / __ init__.py
from .redis import MockRedis
或者只是将helper模块添加到您的中PYTHONPATH
。
回答 1
广义上,conftest.py是一个本地的按目录的插件。在这里,您可以定义目录特定的挂钩和固定装置。在我的情况下,有一个根目录,其中包含项目特定的测试目录。某些常见的魔术位于“ root” conftest.py中。特定于项目-在自己的项目中。除非将夹具广泛使用(在这种情况下,我宁愿直接在测试文件中定义它们),否则在conftest.py中存储夹具时不会发现任何不良情况。
回答 2
我使用该
conftest.py
文件来定义要注入测试中的灯具,这是否正确使用conftest.py
?
是的,通常使用固定装置来准备好用于多个测试的数据。
它还有其他用途吗?
是的,灯具是pytest
在实际测试功能之前(有时是之后)运行的功能。灯具中的代码可以执行您想要的任何操作。例如,夹具可以用于获取要进行测试的数据集,或者夹具也可以用于在运行测试之前使系统进入已知状态。
我可以有多个
conftest.py
文件吗?我什么时候要这么做?
首先,可以将灯具放入单独的测试文件中。但是,要在多个测试文件之间共享灯具,您需要在conftest.py
所有测试的中央位置使用文件。灯具可以通过任何测试共享。如果您希望夹具仅由该文件中的测试使用,则可以将它们放在单独的测试文件中。
其次,可以,您可以conftest.py
在top tests目录的子目录中拥有其他文件。如果这样做,这些较低级别conftest.py
文件中定义的固定装置将可用于该目录和子目录中的测试。
最后,将固定装置放在conftest.py
文件中的测试根目录下将使它们在所有测试文件中均可用。