Использование транзакций при тестировании Sinatra приложения
22 Aug
В прошлый раз я писал о том, что ActiveRecord::Base.establish_connection на самом деле не устанавливает соединения с базой данных. В этот раз я хочу написать о том, как тестировать модели ActiveRecord не в Rails окружении, точнее даже не об этом. Думаю, многие знают о том, что тесты в Rails можно оборачивать в транзакции, т.е. после выполнения теста состояние базы данных не меняется. Я считаю, что это правильный подход, и поэтому решил использовать его и своем текущем приложении.
В первую же очередь подумалось о том, раз это есть в Rails, значит надо его оттуда вытащить. На практике, как обычно это получается, все оказалось не так просто. Надо отметить, что сначала все было хорошо. Все, что мне было нужно, было сосредоточено в active_record/test_case, который тянул за собой файлы из active_support. Так как и то, и другое и так уже было в моем приложении, все представлялось в радужном свете. Не тут-то было, наиболее важная часть, именна та, которая касается transactional fixtures, почему-то находилась в action_controller/integration. Тянуть к себе action_controller мне не хотелось. Изучив немного код, я понял, что на самом деле достаточно просто. Каждую транзакцию следует начать этим кодом:
ActiveRecord::Base.connection.increment_open_transactions
ActiveRecord::Base.connection.transaction_joinable = false
ActiveRecord::Base.connection.begin_db_transaction
И закончить этим:
ActiveRecord::Base.connection.rollback_db_transaction
ActiveRecord::Base.connection.decrement_open_transactions
(код выдран из файла active_record/fixtures)
Вполне достаточно решение, но, как известно большинство велосипедов уже изобретено. В группе обсуждения Sinatra мне подсказали замечательную библиотеку database_cleaner, в первом приближении это именно то, что нужно. Тем более, что автор заявляет:
One of my motivations for writing this library was to have an easy way to turn on what Rails calls “transactional_fixtures” in my non-rails ActiveRecord projects.
Всю необходимую информацию об использовании библиотеки можно прочитать в readme.
