ChatGPT解决这个技术问题 Extra ChatGPT

在pytest中,conftest.py文件有什么用?

我试图了解 conftest.py 文件的用途。

在我的(目前很小的)测试套件中,我在项目根目录中有一个 conftest.py 文件。我用它来定义我注入测试的固定装置。

我有两个问题:

这是 conftest.py 的正确用法吗?它还有其他用途吗?我可以有多个 conftest.py 文件吗?我什么时候想这样做?示例将不胜感激。

更一般地说,您将如何定义 pytest 测试套件中 conftest.py 文件的用途和正确使用?

你让我在 It seems great. However, I feel the documentation could be better.
是的,文档可能会更好。我在整个 pytest 文档中搜索了 conftest.py,尽管有很多关于使用 conftest 文件执行此操作或执行此操作的参考,但文档中没有任何地方表明 当 pytest 进行测试发现时, 找到所有 conftest.py 文件(在进行测试发现的目录结构中)将在测试收集阶段运行 i>(在运行任何测试之前)。必须通过实验自己弄清楚。

G
Gaurav Khurana

这是 conftest.py 的正确用法吗?

是的。 Fixtures 是 conftest.py 的潜在和常见用途。您将定义的夹具将在您的测试套件中的所有测试之间共享。但是,在根 conftest.py 中定义固定装置可能没有用,如果所有测试都没有使用这些固定装置,它会减慢测试速度。

它还有其他用途吗?

是的,它确实。

夹具:为测试使用的静态数据定义夹具。除非另有说明,否则套件中的所有测试都可以访问此数据。这可能是数据以及将传递给所有测试的模块的助手。

外部插件加载:conftest.py 用于导入外部插件或模块。通过定义以下全局变量,pytest 将加载模块并使其可用于测试。插件通常是在您的项目或测试中可能需要的其他模块中定义的文件。您还可以加载一组预定义的插件,如此处所述。 pytest_plugins = "someapp.someplugin"

Hooks:您可以指定诸如 setup 和 teardown 方法等钩子来改进您的测试。对于一组可用的钩子,请阅读 Hooks 链接。示例:def pytest_runtest_setup(item): """ 在 ``pytest_runtest_call(item) 之前调用。""" #do some stuff`

测试根路径:这是一个隐藏的特性。通过在根路径中定义 conftest.py,您将让 pytest 识别您的应用程序模块,而无需指定 PYTHONPATH。在后台, py.test 通过包含从根路径中找到的所有子模块来修改您的 sys.path。

我可以有多个 conftest.py 文件吗?

是的,如果您的测试结构有些复杂,强烈建议您这样做。 conftest.py 个文件具有目录范围。因此,创建有针对性的夹具和助手是一种很好的做法。

我什么时候想这样做?示例将不胜感激。

几种情况可能适合:

为一组特定的测试创建一组工具或挂钩。

根/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"

为某些测试加载一组夹具,但不为其他测试加载。

根/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 继承的挂钩。

根/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 here 的更多信息。

编辑:

如果我需要从不同模块中的多个测试中调用普通的辅助函数怎么办 - 如果我将它们放在 conftest.py 中,它们对我可用吗?或者我应该简单地将它们放在一个 helpers.py 模块中并在我的测试模块中导入和使用它?

您可以使用 conftest.py 来定义您的助手。但是,您应该遵循常规做法。至少在 pytest 中,助手可以用作固定装置。例如,在我的测试中,我有一个模拟 redis 助手,我以这种方式将其注入到我的测试中。

根/助手/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 包含更多测试,您可能会将 redis.py 命名为 conftest.py。但是,由于模棱两可,不鼓励这种做法。

如果您想使用 conftest.py,您只需将该帮助程序放在您的根目录 conftest.py 中,并在需要时注入它。

根/测试/conftest.py

@pytest.fixture
def mock_redis():
    return MockRedis()

根/测试/东西/test.py

def test(mock_redis):
    print(mock_redis.get(stuff))

您可以做的另一件事是编写一个可安装的插件。在这种情况下,您的帮助程序可以在任何地方编写,但它需要定义一个入口点以安装在您的和其他潜在的测试框架中。请参阅this

如果您不想使用固定装置,您当然可以定义一个简单的帮助程序,并在需要的地方使用普通的旧导入。

根/tests/helper/redis.py

class MockRedis():
    # stuff

根/测试/东西/test.py

from helper.redis import MockRedis

def test():
    print(MockRedis().get(stuff))

但是,在这里您可能会遇到路径问题,因为模块不在测试的子文件夹中。您应该能够通过向您的助手添加 __init__.py 来克服这个问题(未经测试)

根/测试/助手/init.py

from .redis import MockRedis

或者只是将帮助模块添加到您的 PYTHONPATH


我遇到的情况是,我的第一个单元测试模块 test_aaaaa.py 实际上试图在 夹具设置在 conftest.py 中完成之前运行。关于为什么会发生这种情况的任何想法?
如果没有 conftest.py,您的测试根路径不会添加到 sys.path,您将看到类似“ModuleNotFoundError: No module named 'foobar'”的错误。
哇,多么详细的答案......非常感谢
伟大而有用的文档值得回答。但是,上面句子中出现的链接“您可以在此处阅读有关 conftest.py 的更多信息”。 (pytest.readthedocs.org/en/latest/plugins.html) 已损坏。我还可以确认 Daniel Goldfarb 上面的评论,即 conftest 又名“什么是 confest”没有顶级文档文件。
很好的答案!这应该是 pytest 文档中的 conftest.py 页面!
v
vinzee

从广义上讲,conftest.py 是一个本地的每个目录插件。在这里,您定义特定于目录的钩子和固定装置。在我的情况下,有一个包含项目特定测试目录的根目录。一些常见的魔法驻留在“根”conftest.py。项目特定 - 在他们自己的项目中。除非它们没有被广泛使用,否则在 conftest.py 中存储固定装置时看不到任何不好的东西(在这种情况下,我更喜欢直接在测试文件中定义它们)


l
lmiguelvargasf

我使用 conftest.py 文件来定义我注入测试的夹具,这是 conftest.py 的正确用法吗?

是的,夹具通常用于为多个测试准备好数据。

它还有其他用途吗?

是的,fixture 是 pytest 在实际测试函数之前(有时是之后)运行的函数。夹具中的代码可以做任何你想做的事情。例如,夹具可用于获取数据集以供测试工作,或者夹具也可用于在运行测试之前使系统进入已知状态。

我可以有多个 conftest.py 文件吗?我什么时候想这样做?

首先,可以将夹具放入单独的测试文件中。但是,要在多个测试文件之间共享夹具,您需要在所有测试的中心位置使用 conftest.py 文件。任何测试都可以共享夹具。如果您希望夹具仅由该文件中的测试使用,它们可以放在单独的测试文件中。

其次,是的,您可以在顶层测试目录的子目录中拥有其他 conftest.py 文件。如果您这样做,这些较低级别 conftest.py 文件中定义的固定装置将可用于该目录和子目录中的测试。

最后,将固定装置放在测试根目录的 conftest.py 文件中将使它们在所有测试文件中都可用。


M
Martin Thøgersen

以下是有关使用 conftest.py to share fixtures 的官方文档:

conftest.py:跨多个文件共享fixture conftest.py 文件用作为整个目录提供fixture 的一种方式。 conftest.py 中定义的固件可以被该包中的任何测试使用,而无需导入它们(pytest 将自动发现它们)。您可以拥有多个包含测试的嵌套目录/包,并且每个目录都可以拥有自己的 conftest.py 和自己的设备,添加到父目录中 conftest.py 文件提供的设备上。