Python 什么';具有功能范围且无拆卸代码的夹具的好处是什么?

Python 什么';具有功能范围且无拆卸代码的夹具的好处是什么?,python,pytest,Python,Pytest,没有拆卸代码的(默认)函数范围夹具有什么优势?为什么不在测试开始时调用函数呢 例如,写作的好处是什么: @pytest.fixture def smtp(): return smtplib.SMTP("smtp.gmail.com") def test_ehlo(smtp): response, msg = smtp.ehlo() # ... 而不是简单地: def create_smtp(): return smtplib.SMTP("smtp.gmail.

没有拆卸代码的(默认)函数范围夹具有什么优势?为什么不在测试开始时调用函数呢

例如,写作的好处是什么:

@pytest.fixture
def smtp():
    return smtplib.SMTP("smtp.gmail.com")

def test_ehlo(smtp):
    response, msg = smtp.ehlo()
    # ...
而不是简单地:

def create_smtp():
    return smtplib.SMTP("smtp.gmail.com")

def test_ehlo():
    smtp = create_smtp()
    response, msg = smtp.ehlo()
    # ...
我理解为什么当我们需要拆卸代码时,夹具是有用的。我也理解为什么具有作用域而非功能的fixture是有用的:我们可能希望在多个测试中重用同一个“外部”对象(以节省创建它所需的时间;或者甚至可以维护它的状态——尽管这似乎相当危险,因为这会在单独的测试之间产生难以看到的耦合)

(默认)功能范围固定装置的优点是什么 拆卸代码?为什么不在程序开始时调用该函数呢 测试

节省垂直空间

考虑这样的情况,每次测试有多个夹具:

import pytest


@pytest.fixture
def value1():
  return 1

@pytest.fixture
def value2():
  return 2

@pytest.fixture
def value3():
  return 3


def test_values(value1, value2, value3):
    assert value1 == 1
    assert value2 == 2
    assert value3 == 3
如果我们按照你的方式来做:

def test_values():
    v1 = value1()
    v2 = value2()
    v3 = value3()

    assert v1 == 1
    assert v2 == 2
    assert v3 == 3
这是额外的三行代码。没什么大不了的,但是如果你有10个测试需要
value1
value2
value3
?现在你有30行额外的垂直空间,基本上没有理由


显然,我们的两个示例都过于简化了(我可以直接调用并内联断言),但我认为很容易看出这对实际代码有何影响。

我开始使用它时也遇到了类似的问题。以下是我的经验:

  • fixture可以设置为autouse=True,也就是说,内联调用可能无法自动触发fixture。这在某些情况下很有用
  • 装置增加了可读性,至少对我来说是这样。通过查看测试的签名,可以了解什么是给定测试的先决条件。从这个意义上讲,它也有助于保持测试和初始化隔离

我认为功能范围固定装置最重要的优点之一是一致性。如果您的所有装置(无论其作用域或分解代码如何)都以完全相同的方式使用,那么它的可读性和逻辑性会更好


此外,如果在将来的某个时候,您决定更改此设备的范围或向其添加一些分解代码,那么您将不需要更改任何测试用例,只需要更改设备的代码。

这是有道理的,尽管我认为不到一半的需要一个设备的测试需要一个以上的测试。是的,我想将所有“外部”测试放在对象转换为测试签名,作为一种文档。