Страницы

воскресенье, 29 апреля 2012 г.

Не используйте Fluent Migrator для интеграционных тестов.

  Библиотеки  миграций баз данных вроде Fluent Migrator и Migrator.Net прочно заняли место среди must have инструментов .net-разработчика. Простота использования подкупает настолько, что появляется соблазн использовать миграции и для создания полноценной тестовой базы данных. Но я не рекомендую так делать по нескольким причинам.

Проблемы.

  Как вы знаете, чтобы быть успешными тесты должны быть быстры. Молниеносно быстры. А прогон миграций на базе данных требует время. Трансформировать миграции в скрипты БД, выполнить их за N-обращений к базе данных – всё это включает в себя затраты самой базы данных, и временные пени за обращение к удалённому сервису. Понятно, что с ростом числа миграций ситуация будет становится всё хуже и хуже.

  А что если в процессе миграций мы заполняем базу данных некоторыми значениями по-умолчанию? Скажем, вносим справочник валют, данные организаций и т.д.? Получаем еще одну проблему: заполненная база данных может создавать неподходящий тестам контекст. В этом случае в коде тестов приходится править данные. Это как минимум непродуктивно. Но хуже того, создаёт ненужную связность между тестами и миграциями, что в свою очередь негативно сказывается на детерминированности и простоте поддержки тестов. Использование разных профилей для развёртывания и тестирования облегчит страдания, но полностью проблему не снимет. Создание единого контекста для всех тестов весьма трудоёмко, и требует особого способа написания тестов. Проще говоря единый контекст для всех тестов – это что-то из области вечного двигателя.  И конечно же, наличие данных лишь усугубляет ситуацию с временными потерями.

Решение.

  Нет необходимости прогонять миграции в каждом тесте. Мы тестируем не миграции, а некий другой функционал, связанный с базой данных. Всё, что необходимо для тестов – это наличии актуальной схемы базы данных. Если бы мы были счастливчиками, и работали с ruby on rails – мы могли использовать функционал schema dumping встроенный в библиотеку миграций. Увы, для fluent-migrator’а проблему придётся решать собственноручно: написать некий schema dumper, или кодогенератор на основе модели предметной области. Впрочем, если вы работаете с NHibernate – то можно воспользоваться встроенным классом SchemaExport для создания пустой базы для тестов. Аналогичные возможности есть и у Entity Framework’а и некоторых других средств доступа к данным.

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

  На мой взгляд, такой подход наиболее оптимален.

2 комментария:

  1. Здравствуйте, Юрий. Спасибо Вам за статью, очень познавательно. Хотелось бы поинтересоваться, был ли у Вас опыт использования миграций для создания структуры in-memory базы данных (SQLite) для целей тестирования домена? Заранее спасибо за ответ (debug@i.ua)

    ОтветитьУдалить
  2. Для SQLite так или иначе пришлось бы испольпользовать подкручивание миграций под синтаксис (https://github.com/schambers/fluentmigrator/wiki/Dealing-with-Multiple-Database-Types). Для меня это лишняя головной боль.
    Мне достаточно того способа, который я описал - NHibernate SchemaExport + in-memory SQLite.

    ОтветитьУдалить