Невозможно создать Python Dataclass (Frozen) внутри функции Pytest, которая использует Fixtures - PullRequest
3 голосов
/ 25 апреля 2020

Я следую вместе с архитектурными паттернами в Python Гарри Персивалем и Бобом Грегори.

В третьей (3) главе они вводят тестирование ORM SQLAlchemy.

Новый тест, который требует приспособление session, оно выбрасывает AttributeError, FrozenInstanceError из-за cannot assign to field '_sa_instance_state'

Может быть важно отметить, что другие тесты не дают сбоя при создании экземпляров OrderLine, но они терпят неудачу если я просто включу session в тестовый параметр (ы).

В любом случае, я прямо в код.

conftest.py

@pytest.fixture
def local_db():
    engine = create_engine('sqlite:///:memory:')
    metadata.create_all(engine)
    return engine


@pytest.fixture
def session(local_db):
    start_mappers()
    yield sessionmaker(bind=local_db)()
    clear_mappers()

model.py

@dataclass(frozen=True)
class OrderLine:
    id: str
    sku: str
    quantity: int

test_orm.py

def test_orderline_mapper_can_load_lines(session):
    session.execute(
        'INSERT INTO order_lines (order_id, sku, quantity) VALUES '
        '("order1", "RED-CHAIR", 12),'
        '("order1", "RED-TABLE", 13),'
        '("order2", "BLUE-LIPSTICK", 14)'
    )
    expected = [
        model.OrderLine("order1", "RED-CHAIR", 12),
        model.OrderLine("order1", "RED-TABLE", 13),
        model.OrderLine("order2", "BLUE-LIPSTICK", 14),
    ]
    assert session.query(model.OrderLine).all() == expected

Ошибка консоли для pipenv run pytest test_orm.py

============================= test session starts =============================
platform linux -- Python 3.7.6, pytest-5.4.1, py-1.8.1, pluggy-0.13.1
rootdir: /home/[redacted]/Documents/architecture-patterns-python
collected 1 item                                                              

test_orm.py F                                                           [100%]

================================== FAILURES ===================================
____________________ test_orderline_mapper_can_load_lines _____________________

session = <sqlalchemy.orm.session.Session object at 0x7fd919ac5bd0>

    def test_orderline_mapper_can_load_lines(session):
        session.execute(
            'INSERT INTO order_lines (order_id, sku, quantity) VALUES '
            '("order1", "RED-CHAIR", 12),'
            '("order1", "RED-TABLE", 13),'
            '("order2", "BLUE-LIPSTICK", 14)'
        )
        expected = [
>           model.OrderLine("order1", "RED-CHAIR", 12),
            model.OrderLine("order1", "RED-TABLE", 13),
            model.OrderLine("order2", "BLUE-LIPSTICK", 14),
        ]

test_orm.py:13: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
<string>:2: in __init__
    ???
../../.local/share/virtualenvs/architecture-patterns-python-Qi2y0bev/lib64/python3.7/site-packages/sqlalchemy/orm/instrumentation.py:377: in _new_state_if_none
    self._state_setter(instance, state)
<string>:1: in set
    ???
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <[AttributeError("'OrderLine' object has no attribute '_sa_instance_state'") raised in repr()] OrderLine object at 0x7fd919a8cf50>
name = '_sa_instance_state'
value = <sqlalchemy.orm.state.InstanceState object at 0x7fd9198f7490>

>   ???
E   dataclasses.FrozenInstanceError: cannot assign to field '_sa_instance_state'

<string>:4: FrozenInstanceError
=========================== short test summary info ===========================
FAILED test_orm.py::test_orderline_mapper_can_load_lines - dataclasses.Froze...
============================== 1 failed in 0.06s ==============================

Дополнительные вопросы

Я понимаю нижележащий лог c и то, что делают эти файлы, но исправьте мои, если мне не хватает элементарного понимания .
1. conftest.py (используется для всех конфигураций pytest) настраивает прибор session, который в основном устанавливает временную базу данных в памяти - использование средств отображения start и clear для обеспечения привязки определений модели orm к значению db.
2. model.py - просто класс данных, используемый для представления объекта atomi c OrderLine.
3. * Класс 1048 * для pytest для поставки приспособления session, чтобы явно setup, execute, teardown дБ для выполнения тестов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...