Как правильно очистить базу данных с помощью фикстур при тестировании с pytest - PullRequest
0 голосов
/ 03 февраля 2020

У меня есть тестовая база данных. Предположим, что там созданы три таблицы:

create table users (
    id serial constraint users_pkey primary key,
    name text not null
);
create table roles (
    id serial constraint roles_pkey primary key,
    name text not null
);
create table users_roles (
    user_id int constraint users_roles_users_fkey references users(id),
    role_id int constraint users_roles_roles_fkey references roles(id)
);

Каждый тест начинается с заполнения базы данных данными с использованием фабрики factory_boy. Типичный тест выглядит следующим образом:

def test_get_user_roles(api_client):
    user = UserFactory.create(id=1)
    role = RolesFactory.create(id=1)
    users_roles = UsersRolesFactory.create(user_id=1, role_id=1)
    response = api_client.get(f"/users/{user.id}/roles")
    assert ...

Я мог очистить таблицу, используя @ pytest.mark.usefixtures ("clear_users_roles", "clear_users", "clear_roles"), где "clear_users_roles", "clear_users", " clear_roles "- это приборы, которые, очевидно, очищают таблицы, если между таблицами не было связей. Но в приведенном выше примере существуют связи (внешние ключи) между таблицей users_roles и пользователем, а также users_roles и ролями, и проблема в том, что приборы работают не по порядку. Поэтому, когда я запускаю свои тесты, я получаю ошибку целостности, потому что, например, приспособление «clear_users» было выполнено до «clear_users_roles», и моя СУБД не может удалить запись, потому что запись все еще ссылается на таблицу «users». Есть ли правильный способ запуска светильников в определенном порядке c? Или, может быть, есть некоторые модели / лучшие практики для такого случая?

1 Ответ

0 голосов
/ 03 февраля 2020

Вы пытались использовать код разрыва в своих приборах с ключевым словом yield?

Пример из документации pytest :

# content of conftest.py

import smtplib
import pytest


@pytest.fixture(scope="module")
def smtp_connection():
    smtp_connection = smtplib.SMTP("smtp.gmail.com", 587, timeout=5)
    yield smtp_connection  # provide the fixture value
    print("teardown smtp")
    smtp_connection.close()
...