передать параметр в прибор Pytest для демонтажа - PullRequest
1 голос
/ 25 октября 2019

Проблема: Очистить тестовые артефакты, созданные из теста. В приведенном ниже примере, как можно удалить одну строку, созданную во время теста, из базы данных с помощью прибора pytest? (Не все следует удалять из таблицы после каждого запуска. В противном случае можно использовать Удалить все строки или удалить таблицу). Идентификатор созданной строки во время теста сохраняется в функциональной переменной.

Можно ли передать переменную, созданную в ходе теста, в качестве параметра в осветитель в pytest? Приспособление должно всегда запускаться независимо от того, завершен ли тест, если он провалился или завершился успешно. Идентификатор строки не будет известен до запуска теста.

Проблема проиллюстрирована с помощью приспособления

@pytest.fixture()
def clean_up_db_row(row_id):
    yield
    delete_from_db(self.row_id). # code to delete the row based on the id


def test_something_added_to_database(clean_up_db_row):
    row_id = create_db_row()  # function under test
    ...
    assert row_id in db  # test that information added to the database

    # the clean_up_db_row fixture will always run but how will it know about the id variable defined in the function?

Если проверка не выполняется в середине теста, строка, добавленная во время теста, не удаляется при добавлении очистки до конца. Потому что тест перестает выполняться.

Пример проблемы без использования приспособления pytest:

def clean_up_db_row(row_id):
    yield
    delete_from_db(row_id). # code to delete the row based on the id


def test_something_added_to_database():
    row_id = create_db_row()  # function under test
    ...
    assert row_id in db  # test that information added to the database
    clean_up_db_row(row_id)  # this won’t run if there is a failure

Решение без приспособления pytest


def clean_up_db_row(row_id):
    yield
    delete_from_db(row_id). # code to delete the row based on the id

def test_something_added_to_database():
    row_id = create_db_row()  # function under test
    ...
    try:
        assert row_id in db  # test that information added to the database
    except Exception as e:
        raise e
    finally:
        clean_up_db_row(row_id)  # this will always run but doesn’t use a fixture

Потенциальное решение с использованием переменной экземпляра класса

class TestCaseCleanUp:

    @pytest.fixture(autouse=True)
    def clean_up_db_row(self):
        yield
        delete_from_db(self.row_id). # code to delete the row based on the id


    def test_something_added_to_database(self):
        self.row_id = create_db_row()  # function under test
        ...
        assert self.row_id in db  # test that information added to the database
        # the autouse fixture can use the self.row_id assigned

1 Ответ

2 голосов
/ 25 октября 2019

Объект, получаемый от прибора, вводит бегун в контекст теста. Это может быть любой объект, который вы хотите, и тест может изменить его.

Вот шаблон, который должен работать для вас:

@pytest.fixture()
def clean_up_db_rows():
    row_ids = []
    yield row_ids
    for row_id in row_ids:
        delete_from_db(row_id)


def test_something_added_to_database(clean_up_db_rows):
    row_id = create_db_row()  # function under test
    clean_up_db_rows.append(row_id)
    ...
    assert row_id in db  # test that information added to the database
...