6

     始める前に、データベースにヒットするテストを「単体テスト」ではないと考えている人がかなりいることを知っています。「統合テスト」の方が適切な名前かもしれません。いずれにせよ、データベースにヒットする開発者テスト。

     単体テストを有効にするために、開発者のローカル データベースを用意し、これをクリアして、各テストの開始時にdbUnitを使用して既知のデータ セットを入力します。テストで使用されるテーブルが何らかの方法で変更され、すべての XML データセットを手動で更新する必要があるまで、これはすべてうまく機能します。これは苦痛です。他の人も同じ問題にぶつかったにちがいないと思います。データベースへの入力が必要なテストでは、何を使用し、テーブル定義の変更をどのように処理しますか? (私は Java を使用していますが、さまざまなテクノロジを利用したソリューションに対してオープンです。)

編集: 少し明確にするために。次のような不自然なテストがあります。

void testLoadRevision() {
    database.clear(); // Clears every table dbUnit knows about.
    database.load("load/trevision.xml", "load/tissue.xml");
    SomeDatabaseThingie subject = new SomeDatabaseThingie(databaseProvider);
    Revision actual = subject.load();
    assert(actual, expected);
}

その中に、tRevision と tIssue という 2 つのテーブルがあります。ロードされたリビジョンは、tIssue からの少量のデータを使用します。その後、tIssue は、リビジョンが気にしない新しいフィールドを取得します。新しいフィールドは「非 null」であり、適切なデフォルトがないため、tIssue.xml が無効になるため、このテストは失敗します。

このような小さな変更では、tIssue を編集するのは難しくありません。しかし、各フローで XML ファイルの数が膨らみ始めると、大量の作業になります。

乾杯、
    mlk

4

3 に答える 3

3

そうですね、既存のものを組み合わせるということですね。

上記のシナリオ:

  1. データベースの移行を書く
  2. データベースの移行を適用します (テスト実行の開始時に手動または自動で)
  3. 制約違反が原因でテストが中断するのを確認します (null 以外)

次のことを行う小さなプログラムになるように拡張できます。

  1. データベースに DbUnit XML を入力する
  2. データベースの移行を適用する
  3. データベースのコンテンツを DbUnit XML (およびオプションで DTD) にインプレースで抽出します (DbUnit ホームページ -> DbUnit FAQ -> データベースからフラットな XML データセットを抽出する方法を参照してください)。
  4. 更新された DbUnit XML (および DTD) をソース管理にチェックインします。

移行を適用するには、 Flywayを心からお勧めします。Sql (プレースホルダー置換あり) と Java ベースの移行の両方をサポートしています。次に、Maven プラグインを使用するか、API を使用してプログラムで移行を適用できます。後者はこのケースに完全に適合します。

完全なワークフローは次のようになります。

  1. データベースの移行を書く
  2. DbUnitXmlDtdUpdater プログラムを実行します
  3. 単体テストのパスを確認する

幸せな日々、

アクセル

免責事項: 私は Flyway の開発者の 1 人です。

于 2010-08-11T07:19:07.553 に答える
3

この質問に対する答えは、次の 2 つの段階に分かれると思います。

スキーマの正式な定義は 1 つだけです。

データベースがどのように見えるかについての定義は 1 つだけである必要があります。通常、データベースのスキーマを指定する SQL DDL スクリプトを使用することを好みます。

単体テストでは、アプリケーションが使用するのと同じデータベース スキーマの正式な定義を使用する必要があり、テストの実行前にその定義に基づいてデータベースを作成し、テストの実行後に完全に削除する必要があります

とはいえ、ツールはスキーマと同期しなくなる可能性があり、ツールで生成されたものを手動で更新する必要があります。たとえば、データベース スキーマに基づいてクラスを自動生成する Entity Framework for .NET を使用しています。スキーマを変更するときは、これらのクラスを更新するようツールに手動で指示する必要があります。面倒ですが、ツールが自動化をサポートしていない限り、それを回避する方法はわかりません。

各テストは空のデータで開始する必要があります

各テストは、データのないデータベースから開始する必要があります。すべてのテストでは、テストの実行に必要なデータのみを入力する必要があり、テストが完了したら、データベースを再度消去する必要があります。

現在行っていることは、General Fixture と呼ばれるアンチパターンのように聞こえます。そこでは、可能な限り広範な一連のシナリオを表す一連のデータをプリロードしようとします。ただし、相互に排他的な条件をテストすることが非常に難しくなり、一部のテストでこの事前に読み込まれたデータを変更すると、テストの相互依存性が発生する可能性があります。

これは、優れた本xUnit Test Patternsで非常によく説明されています。

于 2009-08-28T10:12:58.120 に答える
2

データの変更が必要なデータベーススキーマの進化時に、dbunit xmlフラットファイルが非同期で実行されるという同じ問題があります(必須列の追加のような単純なものであっても)。

いくつかの手書きのスクリプトを使用してすべての xml ファイルを変換することはオプションですが、ライブ データを処理する方法に似た別の抽象化レベルで問題を解決する必要があると思います: 進化的データベース設計。

データベース移行ツールはデルタ スクリプトについて既に認識しているため、一種の dbunit アダプターを用意すると便利です。

問題をカバーする次のブログ エントリが見つかった場合: http://blog.liquibase.org/2007/06/unit-testing-the-database-access-layer.html

テスト データ定義がスキーマと同期しなくなる問題を解決するには、テスト データをデータベースと共に構築して、最初に作成した後に行われたデータベース リファクタリングによって変更されるようにする必要があります。[..] データベースの変更にテスト データを含めることで、データは本番データと同じように自動的に維持されます。メソッドごとにデータセットに対してこの手法を使用すると、データが一度だけ挿入されるため、パフォーマンスが向上するという利点もあります...

しかし、彼自身を追加します:

ただし、メソッドが必要とするすべてのテスト データを 1 か所で処理する必要があるという欠点があります。

...これは、より複雑なシナリオでは不可能だと思います。彼は続けてこう言います:

この手法を容易にするために、実行コンテキストのアイデアを LiquiBase に組み込んで、テスト データの変更をマークし、単体テストを実行する環境にのみ適用できるようにしました。これまでのところ、私は結果に満足しています。データベース スキーマとコードが期待するものとの間に違いがある場合、または SQL にバグがあり、データベースのリファクタリングのためにテストを失っていない場合、テストは失敗します。

リンクは次のとおりです: www.liquibase.org/manual/contexts ですが、少なくとも私が望んでいるものではありません。テストデータをデータベース移行ツールに公開しても問題ありませんが、それでもデータベース テストに非常に近い状態を維持したいと考えています。

誰か考えますか?

于 2010-08-10T16:10:06.517 に答える