Как сделать так, чтобы два выпущенных светильника зависели друг от друга?

В 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

Есть лучший способ сделать это?

3 ответа

Решение

Как вы описали, прибор по умолчанию уже используется для выполнения теста.

На самом деле это нигде не задокументировано явно (или, по крайней мере, я его не нашел), но это несколько неявно: разделение фикстуры между тестами в модуле описывает scope параметр, а область по умолчанию function,

Другие области, например, будут module (поделиться / кэшировать прибор для всех тестов в одном модуле) или session (кешируйте прибор для всей тестовой сессии).

Вы можете вернуть его как объект и использовать третье исправление:

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

Я знаю, что это старый вопрос, но я не вижу того поведения, которое вы описываете, и я действительно отвлекся на эти вопросы и ответы, пока я не подумал: "Так не может работать..." и проверил его на себе. Я пробовал это:

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, похоже, обеспокоен app объект получен login приспособление отличается от 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

... так что это определенно один и тот же объект во всех трех местах. Такие вложенные фикстуры, как этот, "просто работают" для меня, поэтому я либо упускаю суть вопроса, который вы задавали, либо поведение изменилось, либо... что-то еще. Но я хотел оставить это здесь для других, которые приходят искать такие вложенные / зависимые приборы, как это.

Я не ожидал этого, но, похоже, это поведение по умолчанию. Я не смог найти никакой документации по этому поводу, хотя. Подсказки приветствуются.

Другие вопросы по тегам