Как использовать тестовую версию Django и сервер Selenium для использования той же базы данных?

У меня есть проект Django (v1.4, используя Postgresql), для которого я написал кучу рабочих unittests. Они используют FactoryBoy для генерации большей части своих данных.

Теперь я начинаю писать некоторые интеграционные тесты, используя LiveServerTestCase с Selenium. Я только что понял, что мои тесты и тестовый сервер используют разные базы данных. Это означает, что данные, созданные фабриками в моих тестах, недоступны для Selenium.

Я не уверен в лучшем способе прогресса. Я думаю, что я мог бы использовать приспособления для подачи данных, которые будут работать, хотя это боль, которая зашла так далеко, используя фабрики.

Есть ли способ продолжить использование фабрик для генерации данных, которые будут работать для моих тестов Selenium? На самом деле я бы хотел, чтобы мои тесты и LiveServerTestCase использовали одну и ту же базу данных.

Ответ 1

Вы пытались использовать sqlite в качестве базы данных для тестов?

При использовании базы данных SQLite в памяти для запуска тестов, то же самое соединение с базой данных будет совместно использоваться двумя потоками параллельно: нить, в которой запущен живой сервер, и поток, в котором тестовый случай запущен.

из Django docs

Если вы не используете что-либо за пределами обычного ORM, вы также можете воспользоваться ускорениями тестов.

Ответ 2

Я узнал, почему это случилось со мной, и некоторые возможные обходные пути, в том числе Илья Барышев, ответьте выше.

Если ваш тест спускается с Django TestCase, и если ваша база данных поддерживает транзакции, каждый тест запускается в своей собственной транзакции, и никто извне (ни один другой поток, внешний процесс или другой тест) не может видеть объекты, созданные в базы данных по вашему тесту.

LiveServerTestCase использует потоки, поэтому он будет страдать от этой проблемы. Таким образом, дизайнеры наследовали от TransactionTestCase вместо TestCase, что отключает эти транзакции, чтобы изменения были глобально видимыми.

Что со мной произошло, так это то, что я добавил некоторые миксины в свой тестовый класс, и один из них втянул TestCase. Это не вызывает ошибку, но она молча заменяет базовый класс LiveServerTestCase на TestCase, что позволяет транзакции снова, вызывая описанную проблему.

Обходное решение базы данных Ilya SQLite работает, потому что Django содержит код, который обнаруживает при использовании базы данных SQLite :memory:, которая фактически использует одно и то же соединение между потоками, поэтому вы видите тестовые объекты в LiveServerThread, потому что они находятся внутри те же транзакции. Однако это связано с некоторыми оговорками:

Важно предотвратить одновременные запросы к базе данных через это совместное соединение двумя потоками, поскольку это может иногда случайно приводить к сбою тестов. Поэтому вам нужно убедиться, что эти два потока не имеют доступа к базе данных в то же время. В частности, это означает, что в некоторых случаях (например, сразу после нажатия ссылки или отправки формы) вам может потребоваться проверить, что ответ получен Selenium и что следующая страница загружена, прежде чем продолжить выполнение теста. Сделайте это, например, сделав Selenium до тех пор, пока в ответе не будет найден тег HTML (требуется Selenium > 2.13)...

https://docs.djangoproject.com/en/1.4/topics/testing/#live-test-server

В моем случае, как только мы идентифицировали, что autocommit отключается при запуске теста, и отслеживал почему (потому что мы ввели код TestCase, который мы не должны были делать), мы смогли исправить иерархию наследования, чтобы не вытащить TestCase, а затем та же самая база данных была видна как из потока сервера, так и из теста.

Это также работает с базами данных Postgres, поэтому это обеспечит решение для velotron.