23

Play フレームワーク 2.1.0 でリレーショナル データベースを使用するコードをカバーする単体テストを作成したいと考えています。これには多くの可能性があり、すべてが問題を引き起こします。

インメモリ H2 データベースでのテスト

Play フレームワークのドキュメントでは、H2 メモリ内データベースで単体テストを実行することを提案しています。開発と運用に使用されるメイン データベースが他のソフトウェア (つまり、MySQL) を使用している場合でも:

app = Helpers.fakeApplication(Helpers.inMemoryDatabase());

私のアプリケーションは、ストアド プロシージャなどの複雑な RDBMS 機能を使用せず、ほとんどのデータベース アクセス ケースは ebean 呼び出しであるため、MySQL と H2 の両方と互換性があるはずです。

ただし、進化のテーブル作成ステートメントは、 、 などを指定するなど、MySQL 固有の機能を使用しますENGINE = InnoDBDEFAULT CHARACTER SET = utf8のこれらの独自の部分を削除するとCREATE TABLE、MySQL は、私が制御できず、バージョンに依存するデフォルト設定を使用するのではないかと心配しています。アプリケーションをテストおよび開発するには、メインの MySQL 構成を変更する必要があります。

このアプローチを使用した人はいますか (進化を MySQL と H2 の両方と互換性があります)?

それを処理する方法の他のアイデア:

  • MySQL と H2 の別々の進化 (良い考えではありません)
  • H2 に追加の MySQL を無視させるいくつかの方法create table(MySQL 互換モードは機能しませんdefault character set。方法がわかりません。

メイン データベースと同じデータベース ドライバーでのテスト

H2 インメモリ データベースの唯一の利点は、高速であることと、実際の環境に近いため、開発/運用データベースよりも同じデータベース ドライバーでのテストの方が優れている可能性があることです。

Play フレームワークでどのように行うことができますか?

試した:

Map<String, String> settings = new HashMap<String, String>();
settings.put("db.default.url", "jdbc:mysql://localhost/sometestdatabase");
settings.put("db.default.jndiName", "DefaultDS");
app = Helpers.fakeApplication(settings);

ここでは進化が機能しているように見えますが、各テストの前にデータベースをクリーンアップするにはどうすればよいでしょうか? 各テーブルを切り捨てるカスタム コードを作成することによって? テーブルを削除する場合、進化は次のテストの前に再度実行されますか、それともplay testコマンドごとに 1 回適用されますか? それともHelpers.fakeApplication()呼び出しごとに 1 回ですか?

ここでのベストプラクティスは何ですか? dbunitについて聞いたことがありますが、あまり苦労せずに統合することは可能ですか?

4

5 に答える 5

8

まず、見つけにくいバグを避けることができるため、テストと実稼働に同じ RDBMS を使用することをお勧めします。

各テスト間でデータベースをクリーンアップする必要性に関しては、EbeanDdlGeneratorを使用してスクリプトを生成し、クリーンなデータベースを作成し、JUnit の@Beforeアノテーションを使用して、すべてのテストの前にこれらのスクリプトを自動的に実行できます。

を使用すると、次のDdlGeneratorように実行できます。

    EbeanServer server = Ebean.getServer(serverName);
    ServerConfig config = new ServerConfig();
    DdlGenerator ddl = new DdlGenerator((SpiEbeanServer) server, new MySqlPlatform(), config);

このコードは、テストを継承できる基本クラス (または注釈Runnerで使用できるカスタム内) に配置できます。@RunWith

FakeApplicationまた、作成を簡単に自動化し、ボイラープレート コードを回避することもできます。

役立つリンク:

于 2013-02-24T20:46:23.420 に答える
5

各テストの前に、メイン データベースとdbunitをクリーンアップするのと同じデータベース エンジンを使用しました。

public class SomeTest {
    // ...

    @Before
    public void startApp() throws Exception {
        // Set up connection to test database, different from main database. Config better should be used instead of hard-coding.
        Map<String, String> settings = new HashMap<String, String>();
        settings.put("db.default.url", "jdbc:mysql://localhost/somedatabase?characterEncoding=UTF-8&useOldAliasMetadataBehavior=true");
        settings.put("db.default.user", "root");
        settings.put("db.default.password", "root");
        settings.put("db.default.jndiName", "DefaultDS"); // make connection available to dbunit through JNDI
        app = Helpers.fakeApplication(settings);
        Helpers.start(app);

        databaseTester = new JndiDatabaseTester("DefaultDS");

        IDataSet initialDataSet = new FlatXmlDataSetBuilder().build(play.Play.application()
                .resourceAsStream("/resources/dataset.xml"));
        databaseTester.setDataSet(initialDataSet);
        databaseTester.onSetup();
    }

    @After
    public void stopApp() throws Exception {
        databaseTester.onTearDown();
        Helpers.stop(app);
    }
}

dataset.xml各テストの前にこれらのテーブルを空にするように dbunit に指示するテーブル名が含まれているだけです。また、フィクスチャを含めることもできます。

<?xml version="1.0" encoding="UTF-8"?>
<dataset>
  <name_of_my_first_table />
  <name_of_my_second_table />
</dataset>

このアプローチを使用すると、テスト データベースで進化が自動的に実行されるため、テスト データベースからすべてのテーブルを削除すると、テーブルが再作成されます。

テーブルをクリーンアップする必要がある場合のみ dbunit を使用するのはやり過ぎです。クエリを直接発行するか、 ebean を使用してクリーンアップできますDdlGenerator。ただし、データの比較には dbunit も使用します。

は使用しませんHelpers.running。これはRunnableRunnable実装が例外をスローできないためです。テストには非常に不便です。しかし、 のコードを見ると、 を呼び出すrunning()だけなので、これらのメソッドをandで直接呼び出します。Helpers.start()Helpers.stop()@Before@After

テストの実行に H2 を使用しないことにしました: はい、実行は高速ですが、MySQL との違いが大きすぎます。

于 2013-02-28T13:50:16.483 に答える
1

このアプローチを使用した人はいますか (進化を MySQL と H2 の両方と互換性があります)?

MySQL 固有の機能に対する答えを見つけました: How can I unit test for MySQL database with Play 2.x?

于 2013-02-28T22:40:59.677 に答える
1

目標が Slick|JPA|Anorm マッピングと関数の両方を検証することである場合は、DB モックを使用することもできます。

適合する場合、テスト DB よりも単体テストに準拠し、管理が容易になるという利点があります (セットアップ/クリア タスクではなく、同じテスト テーブルへのアクセスを避けるためのテストの同期ではありません)。

Anorm 自体の仕様で使用されている私のフレームワーク Acolyte ( http://github.com/cchantep/acolyte ) を見ることができます (例: https://github.com/playframework/playframework/blob/master/framework/ src/anorm/src/test/scala/anorm/SqlResultSpec.scala )。

于 2014-08-08T11:15:27.240 に答える