Разрыв Pytest базы данных postgresql в Flask происходит до завершения тестов

#python #postgresql #flask #pytest

#python #postgresql #flask #пытест

Вопрос:

Приведенные ниже тесты выполнялись нормально, когда я использовал SQLite в качестве тестовой базы данных. Однако теперь приложению требуется Postgresql, что «вызывает» зависание тестов. Во время выполнения, когда я проверяю через select * from pg_stat_activity , процесс разрыва или db.drop_all() пытается удалить таблицы (некоторые из них удаляются), пока второй запрос test_login_logout все еще выполняется.

Если я удалю db.drop_all() тесты, они будут работать нормально, но, очевидно, база данных не будет уничтожена. Что я делаю не так? Спасибо!

 @pytest.fixture(scope='module')
def test_client():
    app = create_app('testing')
    with app.test_client() as testing_client:
            with app.app_context():
                yield testing_client


@pytest.fixture(scope='module')
def init_database(test_client):

    db.create_all()

    admin_role = Role(name='admin')
    db.session.add(admin_role)

    user = User(username='testuser', password='password', role=admin_role)
    db.session.add(user)

    db.session.commit()

    yield

    db.drop_all()


class TestPublic:

    def test_login_logout(self, test_client, init_database):
        response = test_client.post('/login', data=dict(
            username='testuser', password='password'), follow_redirects=True)
        assert response.status_code == 200
        assert b"Login successful." in response.data

        response = test_client.post('/login', data=dict(
            username='x', password='x'), follow_redirects=True)
        assert response.status_code == 200
        assert b"Invalid username or password." in response.data

        response = test_client.get('/logout', follow_redirects=True)
        assert response.status_code == 200
        assert b"You have been logged out." in response.data
 

Ответ №1:

Удалите db.drop_all() инструкцию оттуда и добавьте эту функцию, она автоматически вызывается после завершения всех тестов:

 def pytest_sessionfinish(session, exitstatus):
    """ whole test run finishes. """
    db.drop_all()
 

Источник: https://docs.pytest.org/en/stable/reference.html#pytest .hookspec.pytest_sessionfinish

Ответ №2:

Я заметил, что статус запроса в postgresql указывает, что это «idle_in_transaction», и после еще нескольких поисков в этой статье указано, что добавление db.session.remove() после выхода поможет решить проблему блокировки. Теперь это работает! Для справки:

 @pytest.fixture(scope='module')
def init_database(test_client):

    db.drop_all()
    db.create_all()

    admin_role = Role(name='admin')
    db.session.add(admin_role)

    user = User(username='testuser', password='password', role=admin_role)
    db.session.add(user)

    db.session.commit()

    yield

    db.session.remove()
    db.drop_all()