12

Java プロジェクトを構築し、関連するユニット/統合テストを実行するために、継続的統合サーバー (Hudson) をセットアップしています。これらのテストのほとんどはデータベースにアクセスし、テスト データは DbUnit XML ファイルに保存されます。

テスト データベース スキーマを自動的に最新の状態に保つ方法を探しています。現在、特定のリリースの SQL スクリプトは、リリース バージョンにちなんで名付けられたディレクトリに格納されています。

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

たとえば、バージョン 0.1.4 の SQL スクリプトは次のとおりです。

scripts\0.1.4\script-0.1.4.sql

問題は、これらのスクリプトにスキーマの変更 (ALTER TABLE など) と静的テーブルへの変更 (USER_TYPE テーブルに新しいロールを追加するなど) が混在していることです。

単体テストの場合は、スキーマの変更のみを適用します。前述のように、単体テストのすべてのデータは DbUnit XML ファイルに保持されるためです。これら 2 種類のデータベースの変更を別々のファイルに分けることはできますが、多くの場合、スキーマの変更とデータの変更の間には依存関係があり、リリースが QA や運用などに適用されるときに何らかの方法で強制する必要があります。

とにかく、これは、誰かがテスト スキーマを自動的に最新の状態に保つための堅牢な方法を思いついたかどうかを尋ねる、非常に長ったらしい言い方です。Unitilsがテスト スキーマを最新の状態に保つためのサポートを提供していることは知っていますが、SQL デルタ スクリプトのデータ更新ステートメントを「無視」できるかどうかはわかりません。

4

6 に答える 6

4

以前の投稿者は Liquibase をオプションとして挙げていましたが、特定のコンテキスト ( Liquibase の Contexts ) で実行されるルールを定義する 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>

このようにして、すべてのデータベース定義を 1 か所にまとめて保持し、テスト コードを実行しているときにのみフィクスチャを挿入できます。

于 2009-06-11T22:12:45.890 に答える
3

ライブ/テスト DB スキーマの段階的な進化を管理する最も管理しやすい方法は、Liquibaseのようなスキーマ移行管理ツールを使用することです。

これにより、選択した環境、テスト環境、またはその他の環境に最新のスキーマ変更を一貫した方法で適用でき、最新のスキーマに対して希望する自動化を実行できます。

于 2009-01-20T15:03:25.597 に答える
2

テストで行うこと:

  • DBバージョンをどこかに保管しています
  • 最初のテストでは、DB全体を破棄し、ゼロから構築します
  • 個々のテストで各スキーマの更新を実行します
  • 「update DB」モジュールを個別のテストとして実行します (すべての変更が既に適用されているため、何もしないでください)。必要に応じて、DB を再度破棄し、これを 1 回実行します。
  • テスト データを DB にロードします (上記のテストの一部は、データ エラーを修正する場合にこれを実行します)。

これで、テスト DB は「実際の」(アプリケーション) テストの準備が整いました。各アプリケーション テストの後、現在のトランザクションをロールバックして、セットアップ後にテスト DB が変更されないようにします。

テストを高速化するために、私は通常 3 つのテスト スイートを用意しています。1 つは DB セットアップを含み、もう 1 つはアプリケーション テストのみを含み、もう 1 つは他の 2 つのスイートを含みます。これにより、テスト DB をすばやくリセットし、アプリ スイートから 1 つのテストを実行できます。

于 2009-01-20T15:00:12.827 に答える
2

私は現在、同様のアプローチを使用しています。私はデータベース移行ツールを調査してきましたが、あなたが説明した問題に対処するツールを見つけていません。

問題は、スキーマの変更により、新しい制約を作成できるようにするためにデータを変更する必要がある場合があることです。この場合、データ更新ステートメントが無視されると、移行は失敗します。

データベース内のすべてのデータを削除する SQL スクリプトをテスト スイートに追加すると、うまくいきますか?

したがって、プロセスは次のようになります。

  1. データベース移行を実行します。
  2. スクリプトを実行して、db 内のすべてのデータを削除します。
  3. ロード テスト データ
  4. テストを実行する
于 2009-01-20T16:26:09.207 に答える
1

この問題を管理するには、 migrateDBを使用します。

このツールは、特定のデータベースの変更が適用されているかどうかを確認するためにデータベースに対して (SQL を介して) 実行できる "テスト" と、テストが "失敗" した場合に実行する関連するアクションのセットがあるという概念に基づいています。たとえば、メタテーブル スキーマにクエリを実行して、テーブルまたは列が存在するかどうかを確認し、存在しない場合は作成する必要がある場合があります。または、特定の行がテーブルに存在するかどうかを確認し、存在しない場合は挿入したい場合があります。いくつかの一般的なテストとアクションが事前に構成されており、独自のテストとアクションを簡単に追加できます (XML 構成のみで、これを行うための新しいコードは必要ありません)。

ちょっとしたおまけとして、これらのテストとアクションのそれぞれは、SQL の「方言」ごとに構成されます (したがって、たとえば、「oracle」方言と「mySQL」方言を使用できます)。つまり、クエリを定義すると、各ダイアレクトの特定のテストとアクションでは、テストまたはアクションの新しいインスタンスごとに新しい SQL は必要なく、複数のターゲット データベースに対して実行できます。

次に、テストと対応するアクションをリストした小さな XML ファイルを維持し、ビルドのたびにデータベースに対してツールを実行します。

それは私たちにとって非常にうまく機能します。

于 2009-01-20T15:33:00.827 に答える