Лучшие практики dbunit для производительности

Каковы некоторые лучшие практики/принципы, которые следует соблюдать, помимо рекомендаций, рекомендованных на фактическом сайте dbunit, которые могут значительно ускорить тесты, а также сохранить их в обслуживании? Я хочу использовать библиотеку, такую ​​как factory girl для java, но это не похоже на то, что это возможно из-за статической типизации.

Мое настоящее мышление состоит в том, чтобы на данный момент иметь 1 набор данных xml для каждого тестового класса - возможно, я разделяю некоторые из них, и, возможно, я этого не делаю. В то время как некоторые тестовые данные могут быть дублированы в разных наборах данных, мне сложно справляться с общими наборами данных в тестах на 3000 единиц/интеграции, и мне еще предстоит еще много.

Поблагодарили бы за какие-либо принципы, которые последуют за проведением тестов, которые будут хорошо и легко поддерживать.

Ответы

Ответ 1

В одном из моих предыдущих заданий мы провели сотни интеграционных тестов с наборами данных, хотя не в DBUnit — тестовая среда была написана с нуля, так как это была очень большая компания, которая может позволить себе этот вид вещей.

Наборы данных были организованы иерархически. Испытуемая система состояла из нескольких (5-10) модулей, и данные испытаний следовали этому шаблону. A unit test script выглядел следующим образом:

 include(../../masterDataSet.txt)
 include(../moduleDataSet.txt)

 # unit-specific test data
 someProperty=someData

Имена свойств были сопоставлены непосредственно с записями БД каким-то причудливым инструментом, о котором я не помню.

Такая же модель может применяться к испытаниям DBUnit. В наборе основных данных вы можете разместить записи всегда, чтобы быть — как словари, начальная загрузка базы данных, как если бы она была установлена ​​с нуля.

В модуле данных вы поставили записи, содержащие тестовые примеры большинства тестов в модуле; Я не предполагаю, что ваш средний тест включает все ваши 70 таблиц базы данных, не так ли? У вас наверняка должны быть некоторые функциональные группы, которые могли бы составлять модуль, даже если приложение монолитно. Попробуйте организовать на нем тестовые данные на уровне модуля.

Наконец, на уровне тестирования, вы только измените свой тестовый набор с минимальным количеством записей, необходимых для этих конкретных тестов.

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

Слово о производительности в конце. На моем 2-ядерном процессоре WinXP на 2,4 ГГц тест DBUnit включает:

  • удаление 14 таблиц,
  • создание 14 таблиц,
  • вставка ca. 100 записей,
  • выполнение тестовой логики,

занимает 1-3 секунды. Журналы показывают, что первые 3 операции занимают меньше секунды, большая часть времени тестирования потребляется Spring. Эта логика выполняется каждым тестом, чтобы избежать зависимостей тестового заказа. Все работает на одной виртуальной машине со встроенным Derby, вероятно, поэтому так быстро.

EDIT: Я думаю, что набор данных DBUnit XML не поддерживает включение других тестовых файлов, его можно преодолеть, используя базовый класс для всех тестов интеграции, например:

public class AbstractITest {

    @Before
    public void setUp() throws Exception {
        //
        // drop and recreate tables here if needed; we use 
        // Spring SimpleJdbcTemplate executing drop/create SQL
        //
        IDataSet masterDataSet = new FlatXmlDataSetBuilder().build("file://masterDataSet.xml");
        DatabaseOperation.CLEAN_INSERT.execute(dbUnitConnection, dataSet);
    }
}

public class AbstractModuleITest extends AbstractITest {

    @Before
    public void setUp() throws Exception {
        super.setUp();
        IDataSet moduleDataSet = new FlatXmlDataSetBuilder().build("file://moduleDataSet.xml");
        DatabaseOperation.CLEAN_INSERT.execute(dbUnitConnection, moduleDataSet);
    }
}

public class SomeITest extends AbstractModuleITest {
    // The "setUp()" routine only here if needed, remember to call super.setUp().

    @Test
    public void someTest() { ... }
}

Ответ 2

Рекомендация в Junit в Action 2e на самом деле не создает слишком много наборов данных (например, для каждого тестового класса), но достаточно, чтобы считаться поддерживаемым. За исключением нескольких исключительных случаев, я нашел возможным использовать базовый набор данных для большинства модульных тестов и отдельные наборы данных для интеграционных тестов. Ограничение использования ExpectedDataSets также является опцией.

Кроме того, я использовал Unitils в сочетании с dbunit для упрощения некоторых настроек и загрузки тестовых данных, поэтому вы можете захотеть рассмотрите его, когда это необходимо.