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

时间:2015-12-25 20:08:21

标签: python testing pytest

我最近发现pytest。看起来很棒。但是,我觉得文档可能更好。

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

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

我有两个问题:

  1. 这是conftest.py的正确用法吗?它有其他用途吗?
  2. 我可以拥有多个conftest.py文件吗?我什么时候想这样做?我们将不胜感激。
  3. 更一般地说,您如何在py.test测试套件中定义conftest.py文件的目的和正确使用?

3 个答案:

答案 0 :(得分:186)

  

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

是的。夹具是conftest.py的潜在和常见用途。该 您将定义的灯具将在您的测试套件中的所有测试中共享。但是,在根conftest.py中定义装置可能是无用的,如果所有测试都不使用此类装置,则会减慢测试速度。

  

它有其他用途吗?

是的。

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

  • 外部插件加载conftest.py用于导入外部插件或模块。通过定义以下全局变量,pytest将加载模块并使其可用于其测试。插件通常是项目中定义的文件或测试中可能需要的其他模块。您还可以按照here所述加载一组预定义插件。

    pytest_plugins = "someapp.someplugin"

  • Hooks :您可以指定挂钩,例如设置和拆卸方法等等,以改善您的测试。对于一组可用的钩子,请阅读here。例如:

    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个文件具有目录范围。因此,创建有针对性的固定装置和助手是很好的做法。

  

我什么时候想这样做?将举例说明。

有几种情况可以适用:

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

<强>根/ 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)

将打印&#34;其他一些东西&#34;。

从根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内运行任何测试,只有&#34;我是mod&#34;打印出来。

您可以详细了解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.py包含更多测试,则可以将conftest.py命名为redis。但是,由于含糊不清,不鼓励这种做法。

如果您想使用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

如果你不想使用灯具,你当然可以定义一个简单的帮手,只需在任何需要的地方使用普通的旧导入。

<强>根/测试器/辅助/ redis.py

class MockRedis():
    # stuff

<强>根/测试/东西/ test.py

from helper.redis import MockRedis

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

但是,此处您可能遇到路径问题,因为模块不在测试的子文件夹中。您应该能够通过向助手

添加__init__.py来克服此问题(未经测试)

<强>根/测试器/辅助/ __初始化__。PY

from .redis import MockRedis

或者只是将帮助程序模块添加到PYTHONPATH

答案 1 :(得分:9)

从广义上讲,conftest.py是一个本地的每个目录插件。在这里,您可以定义特定于目录的挂钩和夹具。在我的情况下,有一个包含项目特定测试目录的根目录。一些常见的魔法驻扎在&#39; root&#39; conftest.py。具体项目 - 在他们自己的。在conftest.py中存储装置时看不到任何坏处,除非它们没有被广泛使用(在这种情况下我更喜欢直接在测试文件中定义它们)

答案 2 :(得分:5)

  

我使用conftest.py文件来定义要注入到测试中的灯具,这是对conftest.py的正确使用吗?

,通常使用固定装置来准备好用于多个测试的数据。

  

它还有其他用途吗?

,fixture是pytest之前(有时)运行的功能 之后,实际测试功能。灯具中的代码可以执行任何操作 想要它。例如,夹具可以用于获取要进行测试的数据集,或者夹具也可以用于在运行测试之前使系统进入已知状态。

  

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

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

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

最后,将夹具放在测试根目录的conftest.py文件中,将使它们在所有测试文件中均可用。