非トランザクションデータベースと統合テスト


8

統合テストで遭遇すると思う1つの問題は、複数のテストが同じデータベースにアクセスすることです。現在、これは問題ではありませんが、同じデータベースにアクセスする複数のアプリケーションが存在することはわかっています。この問題が発生する前に回避する方法を考えているところです。

私がよく見たアイデアはトランザクションを使用することです。起動時にトランザクションを開始してから、ティアダウンでトランザクションをロールバックします。これは、同じデータベーステーブルにアクセスする複数のテストが互いに影響を及ぼさないことを意味します。私の問題は、私の場合、MySQLで使用しているテーブルの85〜95%がトランザクションをサポートしないMyISAMであるということです。

トランザクションをサポートしないストレージエンジンを回避する方法はありますか?それでも、複数のテストが互いに影響を与えずに同じテーブルにアクセスできるようにしますか?私が聞いたところによると、Ruby on Railsテストフレームワークはこのようにトランザクションを使用しますが、どのようにしてこの問題を回避しますか(またはそれらを行いますか)?


同時にテストを実行しますか?
JeffO 2011

私はできた。同じプロジェクトの同時テストは実行しませんが、同じデータベース/テーブルにアクセスする複数のプロジェクトがあります。2つのプロジェクトが同時にテストを実行しているのを見ることができました。
ライアンゼク2011

1
+1テストを同時に実行する必要がある場合、さらに困難になります。
KLE、2011

回答:


4

私の会社では、その議論がありました。持続性はテストにとって大きな問題です。

中途半端になるハックがあります。私たちは彼らとの時間を失わないように決めました:

  • ロールバックするトランザクションを使用します。それは失敗します:
    • 隔離されたトランザクションを(より一般的なトランザクションの内部で)開くことがあるので、テストコードがトランザクションをグリップする前に閉じられています
    • 実際の永続性をテストすることはできません。(テストが1つのトランザクションを閉じ、別のトランザクションでそのデータの影響を受ける複雑なクエリを実行した場合、またはデータを保存して後で再度読み込む場合に何が起こりますか。)
    • コードを完全にテストすることはできません(トランザクションレベルの下のレイヤーのみ。統合テストの欠点を考慮すると十分ではありません)。
  • テストごとに新しいクリーンなデータベースを使用します。それも失敗します:
    • 私たちのテストスイートはすぐに数千のテストに到達します(私たちは大きなチームを持っています)。新しいデータベースをセットアップするには、せいぜい数分しかかかりません(各バージョンの一部である多くのカタログとパラメーターがあるため)。私たちのテストスイートはすぐに終了するまで数か月かかり、数日しか待つことができません。
    • 開発者ごと、またはマシンごとに特定のデータベースインスタンスが必要であり、一度に1つのテストのみを起動するポリシーがあります。Oracle 11を使用してクエリが問題ないことを確認する必要がありますが、コストがかかりすぎます(Oracleライセンス)。
  • 各テスト後に慎重にクリーンアップします(テストフレームワークは、テスト後にコードを実行するためのフックを提供します)。それは失敗します:
    • そのコードdoesとそのテストの完全な一致を維持することは非常にコストがかかりundoesます。一致が完全ではなくなるとすぐに症状が明確にならず、数百行後にテストが失敗する可能性があります。または、失敗するはずのテストが誤ってパスする可能性があります。
    • クリーニングが正しくないエッジケースは常にあります(マシンまたはソフトウェアのクラッシュ?)。これにより、後で実行するための不明な状態が残ります。
    • テストでエラーが表示された場合、データベースの状態は重要な情報ですが、失われます(次のテストの前にクリーンアップして、テストスイートを終了し、開発者に完全な情報を表示するため)。

そこで、有効であることがわかっているポリシーに移動しました。

  • 持っている我々の要求のための自動ユニットテストを
    • 必要に応じて、データベースアクセスをモックします(ただし、通常はJMockは必要ありません。要求された場合は、設計を説明できます)。
    • テストは毎秒100を超える速度で実行されます
    • テストはすばやく記述でき、短くて明確です。
    • テストは永続的な状態に依存しないため、自然に互いに完全に分離されます(複雑なメカニズムは必要ありません)。
  • データベースと個別に統合するテスト(つまり、アプリケーションロジックと統合されていない、リクエストごとに要求)。
    • そのタスクの自動化を検討しましたが、コストがかかり過ぎているように見えました(私の投稿の前の部分を参照)
    • そのため、これらのテストマニュアルを保持しました。クエリを変更する各開発者は、データベース(通常はユーザーインターフェイスを介したエンドツーエンドテストの一部)で再度クエリをテストする必要があります。

2

「トランザクション」がない場合でも、T-SQLの意味では、トランザクションを(用語の一般的な意味で)アトミックにするように努力する必要があります。テストは相互に依存すべきではなく、リバーシブルでなければなりません。公式のロールバックまたはトランザクションスコープがない場合は、独自に作成することをお勧めします。たとえば、単体テストでクリーンアップを実行して、テストで作成されたすべてのレコードを削除することができます。


これは既にトランザクションなしで行われます(最後に、常に空のテーブルでテストを開始するため、テーブルは空になります)が、同時に実行される複数のテストの問題は解決しません。アプリケーションAとアプリケーションBの統合テストを同時に実行していて、どちらもdatabase.table_aに10個のレコードを挿入する場合、テーブルに10個のレコードがあることを確認するテストがあっても、結果は10になります。テストが機能していても、テストは失敗します。これは私が避けようとしているケースです。
ryanzec

@ryanzec-私は完全には従いません。10個のレコードがテーブルにあることを確認するテストがあり、10の結果が得られた場合、テストは合格したようです。
モーガンハーロッカー、2011

@ryanzec-私はあなたが何を意味するのかわかるかもしれません。アプリケーションAが合格するためにテーブル内の10レコードを必要とするが、アプリBが同時にいくつかの追加を挿入した場合、Aのテストは失敗します。この場合、別の方法でテストを作成する必要があります。テストのためにテーブルで10レコードを探すのではなく、トランザクション番号が関連付けられている10レコードを探すために、ある種のトランザクション番号を指定します。
モーガンハーロッカー、2011

0

各ユーザーまたは各実行に、使用するデータベースを上書きさせるだけです。それが私たちの仕事です。次に、2つの同時テストが互いに干渉するという問題は発生しません。

各テスト実行で、マイグレーションを使用してデータベースを構築し、フィクスチャをデータベースに入力して、最後にそれらを破棄します。

DBMSがトランザクションをサポートしている場合、それを初期設定と破棄の最適化として使用します。テストはオプションなしで少し長く実行できますが、オプションです。いつものようにYYMV。

大騒ぎなし、ムスなし。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.