conftest.py
文件的用途。在我的(目前很小的)测试套件中,我在项目根目录下有一个
conftest.py
文件。我使用它来定义我注入到测试中的fixture。我有两个问题:
1. 这是
conftest.py
的正确使用方式吗?它还有其他用途吗?
2. 我可以有多个conftest.py
文件吗?什么时候需要这样做?如果能提供示例将不胜感激。更一般地说,在pytest测试套件中,你如何定义
conftest.py
文件的目的和正确使用方式?conftest.py
文件的用途。conftest.py
文件。我使用它来定义我注入到测试中的fixture。conftest.py
的正确使用方式吗?它还有其他用途吗?
2. 我可以有多个conftest.py
文件吗?什么时候需要这样做?如果能提供示例将不胜感激。conftest.py
文件的目的和正确使用方式?这是正确使用conftest.py吗?
是的,这是正确的用法。Fixture(夹具)是conftest.py
的常见用途。您定义的Fixture将在测试套件中的所有测试之间共享。但是,在根conftest.py
中定义Fixture可能是无用的,并且如果这些Fixture未被所有测试使用,则会减慢测试速度。
它还有其他用途吗?
是的,它有其他用途。
Fixture(夹具):为测试使用的静态数据定义Fixture。除非另有指定,否则所有测试都可以访问此数据。这也可以是模块的辅助数据和helpers,将传递给所有测试。
外部插件加载:使用conftest.py
导入外部插件或模块。通过定义以下全局变量,pytest将加载该模块并使其在测试中可用。插件通常是在您的项目中定义的文件或其他模块,可能需要在您的测试中使用。您还可以像此处所述加载一组预定义插件。
pytest_plugins = "someapp.someplugin"
Hooks(钩子):您可以指定setup和teardown方法等钩子,以改进测试。有关可用的hooks集,请阅读Hooks链接。例如:
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
文件具有目录范围。因此,创建有针对性的fixture和helper是一个好习惯。
那么我什么时候需要这样做?可以举个例子吗?
有几种情况可能适用:
为特定测试组创建一组工具或钩子(hooks)。
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"
根目录/mod2/conftest.py
@pytest.fixture()
def fixture():
return "some other stuff"
根目录/mod2/test.py
def test(fixture):
print(fixture)
将打印“some other stuff”。
覆盖从根conftest.py
继承的挂钩。
root/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
中运行任何测试,只会打印出“I am mod”。
你可以在这里阅读有关conftest.py
的更多信息。
编辑:
如果我需要从不同模块的多个测试调用普通的帮助程序函数-如果我将它们放在conftest.py中,它们是否可用?或者我应该将它们放在helpers.py模块中并在测试模块中导入和使用它们?
您可以使用conftest.py
定义您的帮助程序。但是,您应该遵循常见做法。至少在pytest
中,可以将帮助程序用作固件。例如,在我的测试中,我有一个模拟redis helper,我以这种方式注入到我的测试中。
root/helper/redis/redis.py
@pytest.fixture
def mock_redis():
return MockRedis()
根目录/tests/stuff/conftest.py
pytest_plugin="helper.redis.redis"
根目录/tests/stuff/test.py
def test(mock_redis):
print(mock_redis.get('stuff'))
这是一个测试模块,您可以在测试中自由导入。请注意,如果您的模块redis
包含更多测试,则可以将redis.py
命名为conftest.py
。但是,由于存在歧义,不建议这样做。
如果您想使用conftest.py
,只需将该助手放在根目录下的conftest.py
中,并在需要时注入即可。
根目录/tests/conftest.py
@pytest.fixture
def mock_redis():
return MockRedis()
根目录 / 测试 / 杂项 / test.py
def test(mock_redis):
print(mock_redis.get(stuff))
你可以做的另一件事是编写一个可安装的插件。在这种情况下,你的辅助程序可以在任何地方编写,但需要定义一个入口点以便在你的和其他可能的测试框架中安装。有关详细信息,请参见 此处。
如果你不想使用 fixture,则当然可以定义一个简单的 helper,并在需要它的任何地方使用普通的导入。
root/tests/helper/redis.py
class MockRedis():
# stuff
根目录/测试/材料/测试.py
from helper.redis import MockRedis
def test():
print(MockRedis().get(stuff))
然而,由于模块不在测试的子文件夹中,您可能会遇到路径问题。通过将__init__.py
添加到您的helper中,您应该能够克服这个问题(未经测试)。
root/tests/helper/init.pyfrom .redis import MockRedis
或者将辅助模块添加到您的 PYTHONPATH
中。
pytest
ж–ҮжЎЈдёӯзҡ„conftest.py
йЎөйқўпјҒ - Simeon Nedkov__main__.py
文件中的sys.path,我发现虽然根目录和“tests”目录被列出,但“src”和“src/core”都没有被列出...这是有问题的,因为这意味着__main__.py
无法像正常运行时(=非测试)那样导入同级.py文件。 - mike rodent
pytest_plugin="helper.redis.redis"
应该是 pytest_plugins
- Oleksandr Spazhev在广义上,conftest.py
是一个本地的每个目录插件。在这里,您可以定义特定于目录的钩子和固定装置。在我的情况下,我有一个根目录,其中包含特定于项目的测试目录。一些通用的魔法在“root”conftest.py
中驻扎。项目特定的内容则在它们自己的文件中定义。在conftest.py
中存储装置,除非它们没有被广泛使用(在这种情况下,我更喜欢直接在测试文件中定义)。
我使用
conftest.py
文件定义fixture,并注入到我的测试中,这是conftest.py
的正确用法吗?
是的,fixture通常用于为多个测试准备数据。
它还有其他用途吗?
是的,fixture是一个在实际测试函数之前(有时在之后)由pytest
运行的函数。fixture中的代码可以进行任何你想要的操作。例如,fixture可以用于为测试准备数据集,也可以在运行测试之前将系统置于已知状态。
我可以有多个
conftest.py
文件吗?什么时候需要这样做?
首先,将fixture放入单个测试文件中是可能的。然而,要在多个测试文件之间共享fixture,你需要使用一个位于所有测试的中心位置的conftest.py
文件。fixture可以被任何测试共享。如果你想要fixture仅被该文件中的测试使用,可以将其放在单独的测试文件中。
其次,是的,你可以在顶级测试目录的子目录中拥有其他conftest.py
文件。如果这样做,这些较低级别的conftest.py
文件中定义的fixture将可用于该目录和子目录中的测试。
最后,在测试根目录下的 conftest.py
文件中添加固件将使它们在所有测试文件中可用。
添加此答案是因为有一些评论指出文档中缺少信息,我猜这是在问题最初提出时发生的,但现在已经得到了很好的解释和记录。
从conftest.py:在多个文件之间共享 fixture到页面底部(实际上与 fixture 或设置 pytest 相关的任何内容都可以应用于 conftest.py
)都与 conftest.py
相关。
因此,通过快速扫描文档,以下是主要功能(但不包括):
conftest.py
中的树形层次结构conftest.py
可以覆盖父conftest.py
(但反之不行)请参见此处第三方插件
提供装置现在在被接受的答案中,它说测试根路径:这是一个有点隐藏的功能。通过定义...但是目前为止,最好的方法是将pythonpath
添加到项目根目录下的pytest.ini
中(实际项目根目录,而不是project/tests
),请参见:pythonpath,它可以为您完成所有操作并更加强大。
看起来像:
[pytest]
pythonpath = src1 src2
conftest.py
:跨多个文件共享 fixtures
conftest.py
文件用作为整个目录提供 fixtures 的一种手段。在conftest.py
中定义的 fixtures 可以被该 package 中的所有测试使用,无需导入它们(pytest 会自动发现它们)。您可以拥有多个嵌套的目录/包来包含您的测试,每个目录都可以具有自己的
conftest.py
文件和其自己的 fixtures,添加到父目录中的conftest.py
文件提供的 fixtures 中。
tests1/test.py
只能访问如下所示的 tests1/conftest.py
:project
|-tests1
| |-__init__.py
| |-conftest.py # <- 〇
| |-test.py # Here
| └-subtests
| |-__init__.py
| |-conftest.py # <- ✖
| └-subtest.py
└-tests2
|-__init__.py
|-conftest.py # <- ✖
|-test.py
└-subtests
|-__init__.py
|-conftest.py # <- ✖
└-subtest.py
tests1/subtests/subtest.py
只能访问下面显示的 tests1/subtests/conftest.py
和 tests1/conftest.py
。* 如果在 tests1/subtests/conftest.py
和 tests1/conftest.py
中有相同名称的 fixture(函数),那么 tests1/subtests/subtest.py
将优先访问 tests1/subtests/conftest.py
中的 fixture(函数):project
|-tests1
| |-__init__.py
| |-conftest.py # <- 〇
| |-test.py
| └-subtests
| |-__init__.py
| |-conftest.py # <- 〇
| └-subtest.py # Here
└-tests2
|-__init__.py
|-conftest.py # <- ✖
|-test.py
└-subtests
|-__init__.py
|-conftest.py # <- ✖
└-subtest.py