Тестовый клиент Django против Django-Pytest
Я использую django-pytest для тестирования API Django Rest Framework. У меня есть тестовый модуль, который выглядит примерно так:
class TestClass:
def test_station_is_created(self, db, api_client):
StationFactory(name='foo')
response = api_client.get(reverse('api:stations'))
assert response.status_code == 200
...
def test_no_stations(self, db, api_client):
response = api_client.get(reverse('api:stations'))
assert response.data['data'] == []
Когда я запускаю тесты, я получаю:
________________________________ TestClass.test_no_stations________________________________
path/to/test/module.py:11: in test_no_stations
E assert [OrderedDict(...01251d92f')])] == []
E Left contains more items, first extra item: OrderedDict([...])
Если я проверяю данные, возвращенные с помощью отладчика, я вижу, что это станция, созданная в предыдущем тесте, хотя база данных кажется пустой:
ipdb> response.data['data'][0]['attributes']['name']
foo
ipdb> len(Station.objects.all())
0
Я не знаю, очищает ли pytest базу данных или нет между тестами. Я подозревал, что используются несколько баз данных, но у меня только одна настроена в моих настройках. Хотя, возможно, есть какое-то кеширование, но я прочитал документацию по тестовому клиенту Django и не нашел много. Чего мне не хватать?
2 ответа
Выяснил в чем проблема. Мы также использовали django-cacheops
и ответ попал в кеш вместо того, чтобы снова выполнить запрос. Ирония в том, что я уже думал, что проблема может быть связана с кешем, но моя попытка отключить его не удалась и ввела меня в заблуждение, чтобы я исключил ее как причину проблемы. В конце концов мы выяснили, как правильно его отключить.
Вот способ, которым вы можете отключить кэширование для тестов, если вы используете cacheops и py.test:
from cacheops import invalidate_all
@pytest.fixture(scope='function', autouse=True)
def invalidate_cache():
invalidate_all()
pytest-django действительно изолирует тесты друг от друга, возвращая транзакцию в конце каждого теста.
Если вы хотите убедиться, что в вашей базе данных нет станций, перед тестом добавьте в начале test_no_stations
:
assert not Station.objects.all().exist()
Если это окажется неверным, либо вы что-то упустили в своей конфигурации pytest, либо проблема в вашем коде.