【问题标题】:pytest fixture that gets data from a database - limit to one call?从数据库获取数据的 pytest 夹具 - 限制为一次调用?
【发布时间】:2022-01-11 16:49:38
【问题描述】:

我有一个夹具可以查询 MongoDB 数据库并返回一条记录。

@pytest.fixture
def chicago():
   return GetRecord("CHICAGO,IL")

每次我将此夹具传递给测试时,它都会再次运行查询。有没有关于如何制作它的最佳实践,所以我只运行这个数据库调用一次?我发现我可以做这样的事情,但这似乎违背了固定装置的目的。

chi = GetRecord("CHICAGO,IL")

@pytest.fixture
def chicago():
    return chi

如果这是替代方案,我可以直接传入chi 而不是声明一个夹具。还有其他解决方案吗?

【问题讨论】:

  • 您可以使用会话范围的固定装置 (@pytest.fixture(scope="session"))。
  • @MrBeanBremen 这似乎有点工作,但也似乎比在夹具块之外声明变量要慢。设置会话范围是否需要更多开销?
  • 你确定吗?与数据库查询相比,这里的任何开销都无关紧要——我不知道有任何开销。你量过时间吗?哦,当然有区别:在第一种情况下(全局变量),查询是在加载测试时进行的,在第二种情况下(会话范围的夹具)是在调用第一个测试时进行的,因此可能会改变测量的时间,具体取决于关于你如何衡量它。
  • 我的笔记本电脑可能是后台工作或其他原因,我只是又试了几次,现在看到了预期的性能。如果您想提交您的解决方案作为答案,以便我接受,那就太好了。我无法在 Google 搜索中找到范围设置,因此随着时间的推移,这可能会获得一些关注。

标签: python unit-testing pytest


【解决方案1】:

要仅在特定范围内评估夹具,您可以设置夹具范围。如pytest documentation 中所述,有五个作用域会影响夹具工作的上下文。基本上,fixture 是在作用域开始时设置的,并在作用域结束时进行清理。

如果您需要在会话中的所有测试中只初始化一次夹具,就像您的情况一样,您可以使用会话范围:

@pytest.fixture(scope="session")
def chicago():
   return GetRecord("CHICAGO,IL")

这将被评估一次,正如第一个测试所使用的那样,如果有任何清理代码,则在所有测试执行完成后将被清理。

这里有一个简单的例子来说明这一点:

import pytest

@pytest.fixture(scope="session")
def the_answer():
    print("Calculating...")
    yield 6 * 7
    print("Answered the question!")

def test_session1(the_answer):
    print(the_answer)

def test_session2(the_answer):
    print(the_answer)

def test_session3(the_answer):
    print(the_answer)

这会导致:

$ python -m pytest -s session_based.py
==================== test session starts ====================
...
collected 3 items

session_based.py Calculating...
42
.42
.42
.Answered the question!

==================== 3 passed in 0.32s ====================

如您所见,“计算”只在第一次测试前进行一次,而“清理”在所有测试完成后进行。

分别地,很少使用的包范围的固定装置在测试包中执行一次,模块范围的测试在测试模块中执行一次并在该模块中的测试完成后清理,类范围的测试每次执行一次测试类和函数范围的固定装置(默认)具有使用它们的单个测试的生命周期。

我很确定之前已经回答过了,但由于我找不到匹配的答案,所以给你。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多