如何让两个发布的固定装置相互依赖?

How to have two issued fixtures depend on each other?

test_something() 中,app 实例应与 login 实例使用的实例相同。

@pytest.fixture
def app():
    # ...
    return app

@pytest.fixture
def login(app):
    # ...
    return login

def test_something(self, app, login):
    pass

我尝试的是从第二个固定装置返回两个对象,但我不认为这是惯用的。

@pytest.fixture
def app_and_login(app):
    # ...
    return app, login

def test_something(self, app_and_login):
    app, login = login_and_login

有更好的方法吗?

我没想到会这样,但这似乎是默认行为。不过,我找不到任何关于此的文档。感谢提示。

你可以return它作为对象,并使用第三个夹具:

import pytest
from collections import namedtuple

Auth = namedtuple('Auth', 'app, login')

@pytest.fixture
def app():
    return 'APP'

@pytest.fixture
def login(app):
    return 'Login at %s' % app

@pytest.fixture
def auth(app, login):
    return Auth(app, login)

def test_something(auth):
    assert auth.app in auth.login

如您所述,默认情况下,夹具已经 共享用于测试运行时。

这在任何地方都没有明确记录(或者至少我还没有找到它),但它有点隐含:Sharing a fixture across tests in a module 描述了 scope 参数,默认范围是 function.

其他范围例如是 module(share/cache 同一模块中所有测试的夹具)或 session(为整个测试会话缓存夹具)。

我知道这个问题很老,但我没有看到你描述的行为,我真的被这个问答分心了,直到我想,“它不能以这种方式工作......”并为自己进行了测试。我试过这个:

platform darwin -- Python 3.7.7, pytest-6.0.1, py-1.9.0, pluggy-0.13.1 -- .../bin/python3

我做了这个测试,它通过了:

import collections
import pytest

AppObject = collections.namedtuple("App", ["name", "login"])

@pytest.fixture
def app():
    app = AppObject("appname", "applogin")
    return app

@pytest.fixture
def login(app):
    return app.login

def test_something(app, login):
    assert isinstance(app, AppObject) and app.name == "appname"
    assert isinstance(login, str) and login == "applogin"

OP 似乎担心 login fixture 接收的 app 对象与 app fixture 返回的 app 不同。我不认为会发生这种情况。例如,如果您添加一些有用的 print 语句,如下所示:

import collections
import pytest

AppObject = collections.namedtuple("App", ["name", "login"])

@pytest.fixture
def app():
    app = AppObject("appname", "applogin")
    print("Object id in app fixture: %d" % id(app))
    return app

@pytest.fixture
def login(app):
    print("Object id in login fixture: %d" % id(app))
    return app.login

def test_something(app, login):
    print("Object id in test: %d" % id(app))
    assert isinstance(app, AppObject) and app.name == "appname"
    assert isinstance(login, str) and login == "applogin"

我看到这个输出:

Object id in app fixture: 4451368624
Object id in login fixture: 4451368624
Object id in test: 4451368624

...所以这三个地方绝对是同一个对象。像这样的嵌套固定装置对我来说“只是工作”,所以我要么错过了你问的问题的要点,要么行为发生了变化,或者......其他。但我想把这个留给那些一起来寻找 nested/dependent 像这样的固定装置的人。