Ответ 1
Я много тестирую интеграцию, потому что по-прежнему считаю это самым надежным способом тестирования, когда задействованы процессы, зависящие от данных. У меня также есть несколько разных контекстов и сценарии DDL для обновления баз, поэтому наши ситуации очень похожи.
В результате я оказался Вариантом 4: поддерживал содержимое базы данных unit test через обычный пользовательский интерфейс. Конечно, большинство интеграционных тестов временно изменяют содержимое базы данных как часть фазы "действия" теста (подробнее об этом "временном" позже), но содержимое не настроено при запуске тестового сеанса.
Вот почему.
На каком-то этапе мы также сгенерировали содержимое базы данных в начале тестового сеанса либо с помощью кода, либо путем десериализации файлов XML. (У нас еще не было EF, но в противном случае у нас, вероятно, был бы некоторый метод Seed
в инициализаторе базы данных). Постепенно я начал испытывать опасения при таком подходе. Было очень сложно поддерживать код /XML при изменении модели данных или бизнес-логики, особенно. когда необходимо было разработать новые варианты использования. Иногда я позволял себе небольшое повреждение данных тестов, зная, что это не повлияет на тесты.
Кроме того, данные должны иметь смысл, так как они должны быть как действительными, так и согласованными с данными реального приложения. Один из способов обеспечения того, чтобы генерировать данные самим приложением, или же неизбежно вы каким-то образом продублируете бизнес-логику в методе семян. Обманывать реальные данные на самом деле очень сложно. Это самое главное, что я узнал. Тестирование созвездий данных, которые не представляют реальных случаев использования, - это не только время, это ложная защита.
Итак, я обнаружил, что создаю тестовые данные через интерфейс приложения, а затем тщательно сериализую этот контент в XML или записывая код, который будет генерировать точно то же самое. До того, как однажды мне пришло в голову, что у меня есть данные, которые легко доступны в этой базе данных, почему бы не использовать их напрямую?
Теперь, может быть, вы спросите Как сделать независимыми тесты?
Интеграционные тесты, как и модульные тесты, должны выполняться изолированно. Они не должны зависеть от других тестов и не должны подвергаться их воздействию. Я полагаю, что на фоне вашего вопроса заключается в том, что вы создаете и засеваете базу данных для каждого теста интеграции. Это один из способов достижения независимых тестов.
Но что, если есть только одна база данных и нет семантических скриптов? Вы можете восстановить резервную копию для каждого теста. Мы выбрали другой подход. Каждый тест интеграции выполняется в TransactionScope
, который никогда не выполнялся. Этого очень легко достичь. Каждое тестовое приспособление наследуется от базового класса, который имеет эти методы (NUnit):
[SetUp]
public void InitTestEnvironment()
{
SetupTeardown.PerTestSetup();
}
[TearDown]
public void CleanTestEnvironment()
{
SetupTeardown.PerTestTearDown();
}
и в SetupTeardown
:
public static void PerTestSetup()
{
_tranactionScope = new TransactionScope();
}
public static void PerTestTearDown()
{
if (_tranactionScope != null)
{
_tranactionScope.Dispose(); // Rollback any changes made in a test.
_tranactionScope = null;
}
}
где _tranactionScope
- статическая членная переменная.