Непрерывная интеграция: поддержание схемы тестовой БД в актуальном состоянии - PullRequest
12 голосов
/ 20 января 2009

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

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

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

Например, сценарий SQL для версии 0.1.4:

scripts\0.1.4\script-0.1.4.sql

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

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

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

Ответы [ 6 ]

4 голосов
/ 12 июня 2009

Предыдущий автор перечислял 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="test@test.com" />
    </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>

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

3 голосов
/ 20 января 2009

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

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

2 голосов
/ 20 января 2009

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

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

Будет ли для вас работать сценарий sql, который удаляет все данные в базе данных?

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

  1. запустить миграцию БД.
  2. запустить скрипт для удаления всех данных в БД.
  3. данные нагрузочного теста
  4. запуск тестов
2 голосов
/ 20 января 2009

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

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

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

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

1 голос
/ 20 января 2009

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

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

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

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

У нас это хорошо работает.

0 голосов
/ 26 апреля 2009

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

$ 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, где типом будет dml / ddl, и отфильтровывать сценарии dml.

...