Как избежать мутирования объектов из фиксированных областей видимости в PyTest?

1

Каков наилучший способ избежать побочных эффектов для объектов, возвращаемых из фиксаций в сессионной области?

Мой рецепт заключается в том, чтобы обернуть осветитель в сессионном режиме функциональным, который возвращает копию исходного объекта. Есть ли что-нибудь встроенное в PyTest для этого? Может быть, какой-нибудь декоратор?

import pytest
from pandas import read_csv

@pytest.fixture(scope='session')
def _input_df():
    """Computationally expensive fixture, so runs once per test session.
    As an example we read in a CSV file 5000 rows, 26 columns into a pandas.DataFrame
    """
    df = read_csv('large-file.csv')

    return df


@pytest.fixture(scope='function')
def input_df(_input_df):
    """"This is a function-scoped fixture, which wraps around the session-scoped one
    to make a copy of its result."""
    return _input_df.copy()


def test_df_1(input_df):
    """Inadvertently, this test mutates the object from the input_df fixture"""
    # adding a new column
    input_df['newcol'] = 0
    # we now have 27 columns
    assert input_df.shape == (5000, 27)


def test_df_2(input_df):
    """But since we are getting a copy or the original this test still passes"""
    assert input_df.shape == (5000, 26)
  • 0
    Ваш подход с наличием вспомогательного приспособления в порядке. Если у вас есть много приборов, которые должны возвращать объектные копии, я бы, вероятно, использовал фабрики приборов , но это в основном та же идея.
  • 0
    Я не понимаю вопрос. Вы не ожидаете, что test_df_2 пройдет? Как правило, не следует разрешать одному тесту влиять на результаты других тестов. Если набор тестов отличается, результаты ваших тестов будут непоследовательными. Если вы хотите изменить _input_df.copy () в каждом тесте, верните ссылку на объект из фиксации input_df.
Показать ещё 1 комментарий
Теги:
unit-testing
pytest

1 ответ

0

Вы должны вернуть объект функции копирования из фиксации input_df без его создания:

import pytest
from pandas import read_csv

@pytest.fixture(scope='session')
def _input_df():
    """Computationally expensive fixture, so runs once per test session.
    As an example we read in a CSV file 5000 rows, 26 columns into a pandas.DataFrame
    """
    df = read_csv('large-file.csv')

    return df


@pytest.fixture(scope='function')
def input_df(_input_df):
    """"This is a function-scoped fixture, which wraps around the session-scoped one
    to make a copy of its result."""
    return _input_df.copy


def test_df_1(input_df):
    """Inadvertently, this test mutates the object from the input_df fixture"""
    # adding a new column
    input_df()['newcol'] = 0
    # we now have 27 columns
    assert input_df().shape == (5000, 27)


def test_df_2(input_df):
    """But since we are getting a copy or the original this test still passes"""
    assert input_df().shape == (5000, 26)

Этот пример кода работает на моей машине. test_df_2 тест не проходит в этом случае.

  • 0
    Моя цель не состоит в том, чтобы второй тест провалился, наоборот. Я опубликовал свое решение, ища что-то лучшее, чтобы не писать две функции для каждого такого прибора.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню