在pytest中,conftest.py个文件有什么用?
In pytest, what is the use of conftest.py files?
我最近发现了pytest
。看起来很棒。但是,我觉得文档可能会更好。
我正在尝试了解 conftest.py
文件的用途。
在我的(目前很小的)测试套件中,我在项目根目录下有一个 conftest.py
文件。我用它来定义我注入测试的固定装置。
我有两个问题:
- 这是
conftest.py
的正确用法吗?它还有其他用途吗?
- 我可以拥有多个
conftest.py
文件吗?我什么时候想这样做?示例将不胜感激。
更一般地说,您将如何在 py.test 测试套件中定义 conftest.py
文件的目的和正确使用?
广义上 conftest.py
是一个本地目录插件。在这里您可以定义目录特定的挂钩和固定装置。在我的例子中,有一个包含项目特定测试目录的根目录。一些常用魔法驻扎在'root'conftest.py
。项目特定 - 在他们自己的项目中。在 conftest.py
中存储固定装置没有什么不好,除非它们没有被广泛使用(在那种情况下,我更喜欢直接在测试文件中定义它们)
Is this the correct use of conftest.py?
是的。 Fixtures 是 conftest.py
的潜在和常见用途。这
您将定义的固定装置将在您的测试套件中的所有测试之间共享。但是,在根 conftest.py
中定义固定装置可能没有用,如果所有测试都没有使用此类固定装置,它会减慢测试速度。
Does it have other uses?
是的。
Fixtures:为测试使用的静态数据定义夹具。除非另有说明,否则套件中的所有测试都可以访问此数据。这可能是数据以及 mod 将传递给所有测试的规则的助手。
外部插件加载: conftest.py
用于导入外部插件或mod规则。通过定义以下全局变量,pytest 将加载 module 并使其可用于测试。插件通常是在您的项目或您的测试中可能需要的其他 mod 规则中定义的文件。您还可以按照 here.
的说明加载一组预定义的插件
pytest_plugins = "someapp.someplugin"
Hooks:您可以指定挂钩,例如设置和拆卸方法等,以改进您的测试。对于一组可用的钩子,请阅读 Hooks link。示例:
def pytest_runtest_setup(item):
""" called before ``pytest_runtest_call(item). """
#do some stuff`
测试根路径:这是一个有点隐藏的功能。通过在您的根路径中定义 conftest.py
,您将 pytest
识别您的应用程序 mod 规则,而无需指定 PYTHONPATH
。在后台,py.test mod通过包含从根路径找到的所有子mod规则来确定您的sys.path
。
Can I have more than one conftest.py file?
是的,如果您的测试结构有些复杂,强烈建议您这样做。 conftest.py
文件具有目录范围。因此,创建有针对性的固定装置和助手是一种很好的做法。
When would I want to do that? Examples will be appreciated.
几个案例可能适合:
为一组特定的测试创建一组工具或挂钩。
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"
正在为某些测试加载一组 fixtures,但不为其他测试加载。
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
中的任何测试,只打印“我是mod”。
您可以阅读更多关于 conftest.py
here。
编辑:
What if I need plain-old helper functions to be called from a number
of tests in different modules - will they be available to me if I put
them in a conftest.py? Or should I simply put them in a helpers.py
module and import and use it in my test modules?
您可以使用 conftest.py
来定义您的助手。但是,您应该遵循惯例。至少在 pytest
中,助手可以用作固定装置。例如,在我的测试中,我有一个模拟的 redis 助手,我以这种方式将其注入到我的测试中。
root/helper/redis/redis.py
@pytest.fixture
def mock_redis():
return MockRedis()
root/tests/stuff/conftest.py
pytest_plugin="helper.redis.redis"
root/tests/stuff/test.py
def test(mock_redis):
print(mock_redis.get('stuff'))
这将是一个测试 mod 您可以在测试中自由导入的规则。 注意 如果您的 module redis
包含更多测试,您可以将 redis.py
命名为 conftest.py
。但是,由于含糊不清,不鼓励这种做法。
如果你想使用 conftest.py
,你可以简单地把那个助手放在你的根 conftest.py
中,并在需要的时候注入它。
root/tests/conftest.py
@pytest.fixture
def mock_redis():
return MockRedis()
root/tests/stuff/test.py
def test(mock_redis):
print(mock_redis.get(stuff))
您可以做的另一件事是编写一个可安装的插件。在这种情况下,您的助手可以写在任何地方,但它需要定义一个入口点以安装在您和其他潜在的测试框架中。参见 this。
如果您不想使用固定装置,您当然可以定义一个简单的帮助程序,并在需要的地方使用普通的旧导入。
root/tests/helper/redis.py
class MockRedis():
# stuff
root/tests/stuff/test.py
from helper.redis import MockRedis
def test():
print(MockRedis().get(stuff))
但是,由于 module 不在测试的子文件夹中,您可能会遇到路径问题。您应该能够通过向您的助手
添加 __init__.py
来克服这个问题(未经测试)
root/tests/helper/init.py
from .redis import MockRedis
或者只是将助手 module 添加到您的 PYTHONPATH
。
I use the conftest.py
file to define the fixtures that I inject into my tests, is this the correct use of conftest.py
?
是的,一个fixture通常用于为多个测试准备好数据
Does it have other uses?
是的,一个fixture就是之前pytest
运行的一个函数,有时
之后,实际测试功能。 fixture 中的代码可以做任何你想做的事
想要它。例如,fixture 可用于获取要进行的测试的数据集,或者 fixture 也可用于在 运行 进行测试之前使系统进入已知状态。
Can I have more than one conftest.py
file? When would I want to do that?
首先,可以将固定装置放入单独的测试文件中。但是,要在多个测试文件之间共享 fixture,您需要在所有测试的中心位置使用一个 conftest.py
文件。夹具可以由任何测试共享。如果您希望夹具仅供该文件中的测试使用,则可以将它们放在单独的测试文件中。
其次,是,您可以在顶级测试目录的子目录中包含其他 conftest.py
文件。如果这样做,这些较低级别 conftest.py
文件中定义的装置将可用于该目录和子目录中的测试。
最后,将固定装置放入测试根目录下的 conftest.py
文件将使它们在所有测试文件中可用。
这里是关于使用conftest.py to share fixtures的官方文档:
conftest.py
: sharing fixtures across multiple files
The conftest.py
file serves as a means of providing fixtures for an entire directory. Fixtures defined in a conftest.py
can be used by any test in that package without needing to import them (pytest will automatically discover them).
You can have multiple nested directories/packages containing your tests, and each directory can have its own conftest.py
with its own fixtures, adding on to the ones provided by the conftest.py
files in parent directories.
我最近发现了pytest
。看起来很棒。但是,我觉得文档可能会更好。
我正在尝试了解 conftest.py
文件的用途。
在我的(目前很小的)测试套件中,我在项目根目录下有一个 conftest.py
文件。我用它来定义我注入测试的固定装置。
我有两个问题:
- 这是
conftest.py
的正确用法吗?它还有其他用途吗? - 我可以拥有多个
conftest.py
文件吗?我什么时候想这样做?示例将不胜感激。
更一般地说,您将如何在 py.test 测试套件中定义 conftest.py
文件的目的和正确使用?
广义上 conftest.py
是一个本地目录插件。在这里您可以定义目录特定的挂钩和固定装置。在我的例子中,有一个包含项目特定测试目录的根目录。一些常用魔法驻扎在'root'conftest.py
。项目特定 - 在他们自己的项目中。在 conftest.py
中存储固定装置没有什么不好,除非它们没有被广泛使用(在那种情况下,我更喜欢直接在测试文件中定义它们)
Is this the correct use of conftest.py?
是的。 Fixtures 是 conftest.py
的潜在和常见用途。这
您将定义的固定装置将在您的测试套件中的所有测试之间共享。但是,在根 conftest.py
中定义固定装置可能没有用,如果所有测试都没有使用此类固定装置,它会减慢测试速度。
Does it have other uses?
是的。
Fixtures:为测试使用的静态数据定义夹具。除非另有说明,否则套件中的所有测试都可以访问此数据。这可能是数据以及 mod 将传递给所有测试的规则的助手。
外部插件加载:
的说明加载一组预定义的插件conftest.py
用于导入外部插件或mod规则。通过定义以下全局变量,pytest 将加载 module 并使其可用于测试。插件通常是在您的项目或您的测试中可能需要的其他 mod 规则中定义的文件。您还可以按照 here.pytest_plugins = "someapp.someplugin"
Hooks:您可以指定挂钩,例如设置和拆卸方法等,以改进您的测试。对于一组可用的钩子,请阅读 Hooks link。示例:
def pytest_runtest_setup(item): """ called before ``pytest_runtest_call(item). """ #do some stuff`
测试根路径:这是一个有点隐藏的功能。通过在您的根路径中定义
conftest.py
,您将pytest
识别您的应用程序 mod 规则,而无需指定PYTHONPATH
。在后台,py.test mod通过包含从根路径找到的所有子mod规则来确定您的sys.path
。
Can I have more than one conftest.py file?
是的,如果您的测试结构有些复杂,强烈建议您这样做。 conftest.py
文件具有目录范围。因此,创建有针对性的固定装置和助手是一种很好的做法。
When would I want to do that? Examples will be appreciated.
几个案例可能适合:
为一组特定的测试创建一组工具或挂钩。
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"
正在为某些测试加载一组 fixtures,但不为其他测试加载。
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
中的任何测试,只打印“我是mod”。
您可以阅读更多关于 conftest.py
here。
编辑:
What if I need plain-old helper functions to be called from a number of tests in different modules - will they be available to me if I put them in a conftest.py? Or should I simply put them in a helpers.py module and import and use it in my test modules?
您可以使用 conftest.py
来定义您的助手。但是,您应该遵循惯例。至少在 pytest
中,助手可以用作固定装置。例如,在我的测试中,我有一个模拟的 redis 助手,我以这种方式将其注入到我的测试中。
root/helper/redis/redis.py
@pytest.fixture
def mock_redis():
return MockRedis()
root/tests/stuff/conftest.py
pytest_plugin="helper.redis.redis"
root/tests/stuff/test.py
def test(mock_redis):
print(mock_redis.get('stuff'))
这将是一个测试 mod 您可以在测试中自由导入的规则。 注意 如果您的 module redis
包含更多测试,您可以将 redis.py
命名为 conftest.py
。但是,由于含糊不清,不鼓励这种做法。
如果你想使用 conftest.py
,你可以简单地把那个助手放在你的根 conftest.py
中,并在需要的时候注入它。
root/tests/conftest.py
@pytest.fixture
def mock_redis():
return MockRedis()
root/tests/stuff/test.py
def test(mock_redis):
print(mock_redis.get(stuff))
您可以做的另一件事是编写一个可安装的插件。在这种情况下,您的助手可以写在任何地方,但它需要定义一个入口点以安装在您和其他潜在的测试框架中。参见 this。
如果您不想使用固定装置,您当然可以定义一个简单的帮助程序,并在需要的地方使用普通的旧导入。
root/tests/helper/redis.py
class MockRedis():
# stuff
root/tests/stuff/test.py
from helper.redis import MockRedis
def test():
print(MockRedis().get(stuff))
但是,由于 module 不在测试的子文件夹中,您可能会遇到路径问题。您应该能够通过向您的助手
添加__init__.py
来克服这个问题(未经测试)
root/tests/helper/init.py
from .redis import MockRedis
或者只是将助手 module 添加到您的 PYTHONPATH
。
I use the
conftest.py
file to define the fixtures that I inject into my tests, is this the correct use ofconftest.py
?
是的,一个fixture通常用于为多个测试准备好数据
Does it have other uses?
是的,一个fixture就是之前pytest
运行的一个函数,有时
之后,实际测试功能。 fixture 中的代码可以做任何你想做的事
想要它。例如,fixture 可用于获取要进行的测试的数据集,或者 fixture 也可用于在 运行 进行测试之前使系统进入已知状态。
Can I have more than one
conftest.py
file? When would I want to do that?
首先,可以将固定装置放入单独的测试文件中。但是,要在多个测试文件之间共享 fixture,您需要在所有测试的中心位置使用一个 conftest.py
文件。夹具可以由任何测试共享。如果您希望夹具仅供该文件中的测试使用,则可以将它们放在单独的测试文件中。
其次,是,您可以在顶级测试目录的子目录中包含其他 conftest.py
文件。如果这样做,这些较低级别 conftest.py
文件中定义的装置将可用于该目录和子目录中的测试。
最后,将固定装置放入测试根目录下的 conftest.py
文件将使它们在所有测试文件中可用。
这里是关于使用conftest.py to share fixtures的官方文档:
conftest.py
: sharing fixtures across multiple filesThe
conftest.py
file serves as a means of providing fixtures for an entire directory. Fixtures defined in aconftest.py
can be used by any test in that package without needing to import them (pytest will automatically discover them).You can have multiple nested directories/packages containing your tests, and each directory can have its own
conftest.py
with its own fixtures, adding on to the ones provided by theconftest.py
files in parent directories.