43

autouse=True是否可以仅在特定标记上阻止执行“功能范围”固定装置?

我将以下夹具设置为自动使用,以便自动模拟所有传出请求:

@pytest.fixture(autouse=True)
def no_requests(monkeypatch):
    monkeypatch.setattr("requests.sessions.Session.request", MagicMock())

但是我有一个标记endtoend,我用它来定义一系列测试,这些测试允许外部请求进行更健壮的端到端测试。我想注入no_requests所有测试(绝大多数),但不是像下面这样的测试:

@pytest.mark.endtoend
def test_api_returns_ok():
    assert make_request().status_code == 200

这可能吗?

4

4 回答 4

82

您还可以使用夹具中的request对象来检查测试中使用的标记,如果设置了特定标记,则不要执行任何操作:

import pytest

@pytest.fixture(autouse=True)
def autofixt(request):
    if 'noautofixt' in request.keywords:
        return
    print("patching stuff")

def test1():
    pass

@pytest.mark.noautofixt
def test2():
    pass

输出-vs

x.py::test1 patching stuff
PASSED
x.py::test2 PASSED
于 2016-08-04T09:19:41.343 回答
9

如果您endtoend在特定模块或类中进行测试,您也可以在本地覆盖no_requests固定装置,例如假设您将所有集成测试分组在一个名为的文件中end_to_end.py

# test_end_to_end.py

@pytest.fixture(autouse=True)
def no_requests():
    return

def test_api_returns_ok():
    # Should make a real request.
    assert make_request().status_code == 200

于 2020-08-07T13:54:31.100 回答
5

我无法找到使用 禁用灯具的方法,但我确实找到了一种方法来恢复我的灯具autouse=True中所做的更改。有一个方法可以恢复堆栈上的所有补丁,所以我可以在我的端到端测试中调用它,如下所示:no_requestsmonkeypatchundo

@pytest.mark.endtoend
def test_api_returns_ok(monkeypatch):
    monkeypatch.undo()
    assert make_request().status_code == 200
于 2016-08-03T17:39:12.210 回答
1

取消或更改自动使用将很困难并且可能无法

你不能取消自动使用,因为它是自动使用的。也许您可以根据标记的条件做一些事情来更改自动使用装置。但这将是骇人听闻和困难的。

可能与:

import pytest
from _pytest.mark import MarkInfo

我找不到这样做的方法,但也许@pytest.fixture(autouse=True)可以获得 MarkInfo,如果它返回“endtoend”,则夹具不会设置属性。但是您还必须在夹具参数中设置条件。

即:@pytest.fixture(True=MarkInfo, autouse=True)。类似的东西。但我找不到办法。


建议您组织测试以防止这种情况发生

您可以通过以下任一方式将 no_requests 与端到端测试分开:

  1. 限制您的 autouse 固定装置的范围
  2. 将 no_requests 放入一个类
  3. 不让它成为自动使用,只需将它传递给你需要它的每个 def 的参数

像这样:

class NoRequests:
    @pytest.fixture(scope='module', autouse=True)
    def no_requests(monkeypatch):
        monkeypatch.setattr("requests.sessions.Session.request", MagicMock())
    def test_no_request1(self):
        # do stuff here
    # and so on

这是一个很好的做法。也许不同的组织可以提供帮助


但在你的情况下,这可能是最简单的monkeypatch.undo()

于 2016-08-03T21:52:37.087 回答