Подтвердить что ты не робот

Непрерывная интеграция: обновление схемы тестовой БД

Я создаю сервер непрерывной интеграции (Hudson) для создания проекта Java и запускаю соответствующие тесты unit/integration. Большинство этих тестов обращаются к базе данных, а тестовые данные хранятся в XML файле DbUnit.

Я ищу способ автоматического поддержания схемы тестовой базы данных в актуальном состоянии. В настоящее время SQL script для конкретной версии хранится в каталоге с именем после версии выпуска:

└───scripts
    ├───0.1.0
    ├───0.1.1
    ├───0.1.2
    ├───0.1.4

Например, SQL script для версии 0.1.4 -

scripts\0.1.4\script-0.1.4.sql

Проблема заключается в том, что эти скрипты содержат смесь изменений схемы (например, ALTER TABLE...) и изменения статических таблиц (например, добавьте новую роль в таблицу USER_TYPE).

В случае модульных тестов я хочу только применить изменения схемы, потому что, как упоминалось выше, все данные для модульных тестов хранятся в XML файле DbUnit. Хотя я мог бы разделить эти два типа изменений базы данных на разные файлы, часто возникает зависимость между изменениями схемы и изменениями данных, которые необходимо будет каким-то образом применять, когда релиз применяется к QA, производству и т.д.

В любом случае, это всего лишь очень длинный способ спросить, есть ли у кого-нибудь надежный способ автоматически обновить свою тестовую схему? Я знаю Unitils имеет некоторую поддержку для поддержания тестовой схемы в актуальном состоянии, но я не уверен, может ли она игнорировать 'операторы обновления данных в сценариях SQL-дельта.

4b9b3361

Ответ 1

В предыдущем плакате список Liquibase как опция, однако они не указали на способность Liquibase определять правила, которые выполняются в определенных контекстах (Контексты в Liquibase). Это позволяет вам иметь обновления схемы, не помеченные каким-либо конкретным контекстом, и светильники для модульных тестов, помеченные как контекст test. Таким образом, светильники будут вставлены только после запуска модульных тестов.

Вот пример набора изменений Liquibase, который содержит схему и светильники:

<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.9 http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.9.xsd">
  <changeSet author="avalade" id="1">
    <createTable tableName="users">
      <column autoIncrement="true" name="id" type="long">
        <constraints nullable="false" primaryKey="true" />
      </column>
      <column name="email" type="varchar(255)" />
    </createTable>
  </changeSet>
  <changeSet author="avalade" id="2" context="test">
    <insert tableName="user">
      <column name="id" value="1" />
      <column name="email" value="[email protected]" />
    </insert>
  </changeSet>
</databaseChangeLog>

Затем, если вы используете Spring для управления своими DAO, вы можете поместить следующее в свой файл контекста приложения, который вы развертываете:

<bean id="liquibase" class="liquibase.spring.SpringLiquibase">
  <property name="dataSource" ref="dataSource" />
  <property name="changeLog" value="classpath:dbChangelog.xml" />
</bean>

Для файла контекста приложения, который вы используете в своих модульных тестах, настройте Liquibase с дополнительным свойством контекста:

<bean id="liquibase" class="liquibase.spring.SpringLiquibase">
  <property name="dataSource" ref="dataSource" />
  <property name="changeLog" value="classpath:dbChangelog.xml" />
  <property name="contexts" value="test" />
</bean>

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

Ответ 2

То, что мы нашли как наиболее управляемый способ управления постепенной эволюцией живых/тестовых схем БД, использует инструмент управления миграцией схемы, например Liquibase

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

Ответ 3

Что я делаю в своих тестах:

  • Я сохраняю версию DB где-то
  • В первом тесте я разрушаю всю БД и строю ее с нуля
  • Я запускаю каждое обновление схемы в отдельном тесте
  • Я запускаю модуль "Обновление БД" в качестве индивидуального теста (не должен ничего делать, потому что все изменения уже применяются). При желании я снова сбрасываю DB и запускаю его один раз.
  • Я загружаю тестовые данные в БД (некоторые из вышеприведенных тестов сделают это, если они исправят ошибки данных).

Теперь тестовая БД готова к "реальным" (прикладным) испытаниям. После каждого из тестов приложения я откатываю текущую транзакцию, поэтому тестовая БД никогда не изменяется после установки.

Чтобы ускорить тестирование, я обычно имею три тестовых набора: один, который содержит в настройке БД, тот, который содержит только те тесты приложений и тот, который содержит два других набора. Это позволяет мне быстро reset тестовую БД и запустить один тест из набора приложений.

Ответ 4

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

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

Добавил бы sql script в ваш тестовый пакет, который удалит вам все данные в базе данных?

Таким образом, процесс будет следующим:

  • выполнить миграцию db.
  • запустите script, чтобы удалить все данные в db.
  • данные теста нагрузки
  • запустить тесты

Ответ 5

Я использую migrateDB для решения этой проблемы.

Этот инструмент основан на понятии, что есть "тесты", которые вы можете выполнить (через SQL) в своей базе данных, чтобы увидеть, было ли применено заданное изменение базы данных, и коррелирующий набор действий для выполнения, если тест "не работает" ". Например, вам может потребоваться запросить схему метаданных, чтобы увидеть, существует ли таблица или столбец, а если нет, создайте ее. Или вы можете посмотреть, существует ли определенная строка в таблице, а если нет, вставьте ее. Он поставляется с несколькими стандартными тестами и действиями, предварительно сконфигурированными, и очень легко добавить свои собственные (только с конфигурацией XML - никакого нового кода для этого).

В качестве небольшого бонуса каждый из этих тестов и действий настроен для каждого "диалекта" SQL (так, например, у вас может быть диалект "оракул" и диалект "mySQL".) Это означает, что как только вы определить запросы для данных тестов и действий для каждого диалекта, каждый новый экземпляр теста или действия не требует нового SQL и может быть выполнен против нескольких целевых баз данных.

Затем вы просто поддерживаете небольшой XML файл, в котором перечислены тесты и соответствующие действия, и запускайте инструмент против вашей базы данных после каждой сборки.

Это хорошо работает для нас.

Ответ 6

Вот что мы делаем:

$ find src/sql/ | grep -v /.svn
src/sql/
src/sql/0000-system.sql
src/sql/0000-system.sql.dev.log
src/sql/0000-system.sql.prod.log
src/sql/0000-system.sql.test.log
src/sql/0001-usgn.sql
src/sql/0001-usgn.sql.dev.log
src/sql/0001-usgn.sql.prod.log
src/sql/0001-usgn.sql.test.log
src/sql/0002-usgn.sql
src/sql/0002-usgn.sql.dev.log
src/sql/0002-usgn.sql.prod.log
src/sql/0002-usgn.sql.test.log
src/sql/0003-usgn.sql
src/sql/0003-usgn.sql.dev.log
src/sql/0003-usgn.sql.prod.log
src/sql/0003-usgn.sql.test.log
src/sql/0004-system.sql
src/sql/0004-system.sql.dev.log
src/sql/0005-usgn.sql
src/sql/purge.sql

у нас есть scriptseq ### - databaseusercredential.sql

Теперь наши тесты всегда позволяют неизвестно начать состояние данных в БД. Если бы вы не могли этого сделать, я бы предложил вам использовать SEQ-CRED-TYPE.sql, где type будет dml/ddl и отфильтровать скрипты dml.