#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()