2009-01-20 16 views
12

Konfiguruję serwer ciągłej integracji (Hudson), aby zbudować projekt Java i uruchomić odpowiednie testy jednostki/integracji. Większość tych testów uzyskuje dostęp do bazy danych, a dane testowe są przechowywane w pliku XML DbUnit.Ciągła integracja: aktualizowanie testowego schematu bazy danych

Poszukuję sposobu automatycznego aktualizowania schematu bazy danych testowych. Obecnie skrypt SQL dla danej wersji jest przechowywany w katalogu o nazwie po wersji wydania:

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

Na przykład, skrypt SQL do wersji 0.1.4 jest

scripts\0.1.4\script-0.1.4.sql 

Problem polega na tym, że te skrypty zawierają mieszaninę zmian schematu (np. ALTER TABLE ...) i zmiany w tabelach statycznych (np. dodaj nową rolę do tabeli USER_TYPE).

W przypadku testów jednostkowych chcę zastosować tylko zmiany schematu, ponieważ, jak wspomniano powyżej, wszystkie dane dotyczące testów jednostkowych są przechowywane w pliku XML DbUnit. Chociaż mogę oddzielić te dwa typy zmian w bazie danych na różne pliki, często będzie zależność między zmianami schematu a zmianami danych, które będą wymagać w jakiś sposób wymuszone, gdy wersja zostanie zastosowana do kontroli jakości, produkcji itp.

W każdym razie, jest to bardzo długotrwały sposób pytania, czy ktoś wymyślił solidny sposób automatycznego aktualizowania swojego schematu testowego? Wiem, że Unitils ma pewne wsparcie dla utrzymywania aktualności schematu testowego, ale nie jestem pewien, czy może "zignorować" instrukcje aktualizacji danych w skrypcie delta SQL.

Odpowiedz

2

Co robię w moich testów:

  • trzymam DB wersję gdzieś
  • W pierwszym teście, ja zburzyć cały DB i zbudować go od nowa
  • uruchomić każdą aktualizację schematu w indywidualnym teście uruchamiam moduł "update DB" jako indywidualny test (nie mogę nic zrobić, ponieważ wszystkie zmiany zostały już zastosowane). Opcjonalnie ponownie zburzę DB i uruchomię to raz.
  • Załaduję dane testowe do DB (niektóre z powyższych testów zrobią to, jeśli poprawią błędy danych).

Teraz testowy DB jest gotowy do testów "rzeczywistych" (aplikacji). Po każdym testowaniu aplikacji wycofuję bieżącą transakcję, więc testowa baza danych nigdy się nie zmienia po zakończeniu instalacji.

Aby przyspieszyć testowanie, zwykle mam trzy zestawy testów: jeden, który zawiera ustawienia DB, taki, który zawiera tylko testy aplikacji i taki, który zawiera dwa pozostałe pakiety. To pozwala mi szybko zresetować testowy DB i uruchomić pojedynczy test z pakietu aplikacji.

3

Co odkryliśmy jak najbardziej rozsądny sposób zarządzania stopniową ewolucję na żywo/test DB schematów jest za pomocą narzędzia do zarządzania migracją schematu podobnego Liquibase

To pozwala nam na zastosowanie najnowszych zmian schematu na cokolwiek środowiska my więc wybierz, przetestuj lub w inny sposób, w spójny sposób, który następnie pozwala nam na uruchamianie dowolnej automatyzacji, jakiej chcemy, wbrew aktualnemu schematowi.

1

Używam migrateDB do zarządzania tym problemem.

Narzędzie to opiera się na założeniu, że istnieją "testy", które można wykonać (za pośrednictwem SQL) w bazie danych, aby sprawdzić, czy dana zmiana bazy danych została zastosowana, oraz zestaw korelacji czynności do wykonania, jeśli test " zawiedzie. " Na przykład może zajść potrzeba wysłania zapytania do schematu meta-tabeli, aby sprawdzić, czy istnieje tabela lub kolumna, a jeśli nie, to ją utworzyć. Możesz też sprawdzić, czy dany wiersz istnieje w tabeli, a jeśli nie, wstaw go. Zawiera kilka typowych testów i wstępnie skonfigurowanych akcji, a bardzo łatwo dodać własne (tylko z konfiguracją XML - nie trzeba do tego nowego kodu).

Jako mała premia, każdy z tych testów i działań jest skonfigurowane dla każdego "dialektu" SQL (tak, na przykład, możesz mieć dialekt "oracle" i dialekt "mySQL".) Oznacza to, że po zdefiniowaniu zapytań dla danych testów i akcji dla każdego dialektu, każda nowa instancja testu lub działania nie wymaga nowego SQL i może być wykonane przeciwko wielu docelowym bazom danych.

Następnie wystarczy zachować mały plik XML, który zawiera listę testów i odpowiednich działań, i uruchomić narzędzie w bazie danych po każdym kompilacji.

Działa to całkiem dobrze dla nas.

2

Obecnie stosuję podobne podejście. Badałem narzędzia do migracji baz danych i nie znalazłem takiego, które rozwiązałoby problem, który opisujesz.

Problem polega na tym, że czasami zmiana schematu wymaga zmiany danych, aby umożliwić tworzenie nowych wiązań itp. W takim przypadku migracja danych nie powiodłaby się.

Czy dodanie skryptu sql do zestawu testów, który spowoduje usunięcie wszystkich danych z bazy danych?

więc proces będzie:

  1. prowadzony db migracji.
  2. uruchom skrypt, aby usunąć wszystkie dane w db.
  3. danych testowych obciążenie
  4. testy zakończą
0

Oto, co robimy:

$ 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 

mamy scriptseq ### - databaseusercredential.sql

Teraz nasze testy, zawsze pozwalają dla nieznanego stanu początkowego danych w DB. Jeśli nie mógłbyś tego zrobić, sugerowałbym użycie SEQ-CRED-TYPE.sql gdzie typem byłby dml/ddl i odfiltrowanie skryptów dml.

4

Poprzedni plakat opublikował Liquibase jako opcję, jednak nie wspomniał o zdolności Liquibase do definiowania reguł, które działają w określonych kontekstach (Contexts in Liquibase). Dzięki temu aktualizacje schematów nie są oznaczone żadnym konkretnym kontekstem, a urządzenia testów jednostkowych są oznaczone jako kontekst test. W ten sposób urządzenia zostaną wstawione dopiero po uruchomieniu testów jednostkowych.

Oto przykład zmiany zestawu Liquibase który zawiera schemat i opraw:

<?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> 

Następnie, jeśli używasz Wiosna zarządzać swoją DAO'S, można umieścić następujące w kontekst aplikacji plik, który jesteś wdrażania:

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

Dla pliku kontekst aplikacji, których używasz w swoich testach jednostkowych skonfigurować Liquibase z dodatkową właściwość kontekstu:

<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> 

W ten sposób można przechowywać wszystkie definicje bazy danych w jednym miejscu i wstawiać tylko urządzenia, gdy uruchamiasz kod testowy.

Powiązane problemy