70

私は新しいプロジェクトの始まりに近づいており、(あえぎ!)初めて、私のプロジェクトに単体テストを含めようとしています。

単体テスト自体のいくつかを考案するのに苦労しています。簡単にテストできるメソッドがいくつかあります (2 つの値を渡して、期待される出力を確認します)。データベースに対してクエリを実行するなど、より複雑なことを行っているコードの他の部分があり、それらをテストする方法がわかりません。

public DataTable ExecuteQuery(SqlConnection ActiveConnection, string Query, SqlParameterCollection Parameters)
{
    DataTable resultSet = new DataTable();
    SqlCommand queryCommand = new SqlCommand();
    try
    {
        queryCommand.Connection = ActiveConnection;
        queryCommand.CommandText = Query;

        if (Parameters != null)
        {
            foreach (SqlParameter param in Parameters)
            {
                 queryCommand.Parameters.Add(param);
            }
        }

        SqlDataAdapter queryDA = new SqlDataAdapter(queryCommand);
        queryDA.Fill(resultSet);
    }
    catch (Exception ex)
    {
        //TODO: Improve error handling
        Console.WriteLine(ex.Message);
    }

    return resultSet;
}

このメソッドは基本的に、データベースから一部のデータを抽出するために必要なすべての要素を取り込み、そのデータを DataTable オブジェクトで返します。

最初の質問はおそらく最も複雑です。このような状況で何をテストすればよいでしょうか?

それが解決したら、データベース コンポーネントをモック アウトするか、実際の DB に対してテストを試みるかという問題が生じます。

4

10 に答える 10

50

何をテストしていますか?

私の頭の上から、3つの可能性があります:

A. DAO (データ アクセス オブジェクト) クラスをテストして、データベースに渡される値/パラメーターが正しくマーシャリングされていること、およびデータベースから取得した結果が正しくマーシャリング/変換/パッケージ化されていることを確認します。

この場合、データベースに接続する必要はまったくありません。データベース(またはJDBC、(N)Hibernate、iBatisなどの中間層)をモックに置き換える単体テストが必要です。

B. (生成された) SQL の構文の正確性をテストしている。

この場合、SQL ダイアレクトが異なるため、RDBMS のすべての癖をモックしようとするのではなく、RDBMS の正しいバージョンに対して (おそらく生成された) SQL を実行する必要があります (機能を変更する RDBMS のアップグレードがあなたのテスト)。

C. SQL のセマンティックの正確性をテストしている。つまり、特定のベースライン データセットに対して、操作 (アクセス/選択、ミューテーション/挿入、更新) が期待される新しいデータセットを生成することをテストしている。

そのためには、 dbunit (ベースラインを設定し、結果セットを予想される結果セットと比較することができます) のようなものを使用するか、ここで概説する手法を使用して、データベース内で完全にテストを実行することをお勧めします。SQL クエリをテストします

于 2009-08-02T00:36:58.237 に答える
38

これが、(IMHO)単体テストが開発者の側に誤った安心感を生み出すことがある理由です。データベースと通信するアプリケーションでの私の経験では、エラーは通常、データが予期しない状態(異常な値や欠落した値など)になっていることが原因です。単体テストでデータアクセスを定期的にモックアップする場合、実際にはまだこの種のエラーに対して脆弱であるにもかかわらず、コードはうまく機能していると思うでしょう。

あなたの最善のアプローチは、テストデータベースを手元に置いて、くだらないデータの塊でいっぱいにし、それに対してデータベースコンポーネントのテストを実行することだと思います。あなたのユーザーがあなたのデータを台無しにするよりもはるかに優れていることを覚えている間ずっと。

于 2009-08-02T00:46:26.133 に答える
15

ユニットテストの要点は、ユニットを分離してテストすることです(当然のことです)。データベース呼び出しの要点は、別のユニット (データベース)と統合することです。エルゴ: データベース呼び出しを単体テストするのは意味がありません。

ただし、データベース呼び出しの統合テストを行う必要があります (必要に応じて、単体テストに使用するのと同じツールを使用できます)。

于 2009-08-03T01:11:24.287 に答える
10

神を愛するために、すでに入力されているライブデータベースに対してテストしないでください。しかし、あなたはそれを知っていました。

一般に、ユーザーの認証、電話帳/組織図のエントリの検索など、各クエリがどのような種類のデータを取得するかについては、すでに理解しています。関心のあるフィールドがわかっていて、それらにどのような制約が存在するか(たとえば、、など)がわかっていUNIQUEますNOT NULL。あなたはデータベース自体ではなく、データベースと相互作用するコードを単体テストしているので、それらの関数をテストする方法の観点から考えてください。フィールドがである可能性がある場合は、コードが値を正しくNULL処理することを確認するテストを行う必要があります。NULLフィールドの1つが文字列(、、、、CHAR& c)の場合はVARCHARTEXTエスケープ文字を正しく処理していることを確認してください。

ユーザーがデータベースに何か*を入れようとし、それに応じてテストケースを生成するとします。これにはモックオブジェクトを使用することをお勧めします。

*望ましくない、悪意のある、または無効な入力を含みます。

于 2009-08-01T23:41:55.827 に答える
5

厳密に言えば、データベースまたはファイル システムに対して書き込み/読み取りを行うテストは単体テストではありません。(ただし、統合テストであり、NUnit または JUnit を使用して記述されている場合があります)。単体テストは、依存関係を分離して、単一のクラスの操作をテストすることになっています。したがって、インターフェイス層とビジネス ロジック層の単体テストを作成する場合、データベースはまったく必要ありません。

わかりましたが、データベース アクセス層の単体テストはどのように行うのでしょうか? この本からのアドバイスが気に入っています: xUnit Test Patterns (リンクは本の「Testing w/DB」の章へのリンクです。キーは次のとおりです:

  • 往復テストを使用する
  • 「実際の」単体テストよりもはるかに遅く実行されるため、データ アクセス テスト フィクスチャに多くのテストを記述しないでください。
  • 実際のデータベースでのテストを避けることができる場合は、データベースなしでテストします
于 2009-08-02T00:02:10.700 に答える
4

以下を除くすべてを単体テストできます。queryDA.Fill(resultSet);

を実行するとすぐにqueryDA.Fill(resultSet)、データベースをモック/偽造するか、統合テストを行う必要があります。

私は、統合テストが悪いとは考えていません。それは、別の種類のバグをキャッチし、偽陰性と偽陽性の可能性が異なり、あまり頻繁に行われる可能性が低いということです。スロー。

このコードの単体テストを行う場合、パラメーターが正しくビルドされていることを検証します。コマンド ビルダーは正しい数のパラメーターを作成しますか? それらはすべて値を持っていますか?null、空の文字列、および DbNull は正しく処理されますか?

実際にデータセットを埋めることは、DAL の範囲外の不安定なコンポーネントであるデータベースをテストすることです。

于 2009-08-02T01:24:57.407 に答える
2

単体テストでは、通常、データベースをモックまたは偽造します。次に、依存性注入を介してモックまたは偽の実装を使用して、メソッドをテストします。また、データベース内の制約や外部キー関係などをテストするいくつかの統合テストもあるでしょう。

何をテストするかについては、メソッドがパラメーターからの接続を使用していること、クエリ文字列がコマンドに割り当てられていること、返された結果セットが期待値を介して提供しているものと同じであることを確認します。 Fill メソッドで。注 - パラメータを変更する Fill メソッドよりも、値を返す Get メソッドをテストする方がおそらく簡単です。

于 2009-08-01T23:28:53.247 に答える
1

これを適切に行うには、何らかの依存性注入 (DI) を使用する必要がありますが、.NET にはいくつかあります。私は現在 Unity Framework を使用していますが、もっと簡単なフレームワークもあります。

このテーマに関するこのサイトからの 1 つのリンク を次に示しますが、他にもリンクがあります。

これにより、モック クラスにインターフェースを実装させるだけで、アプリケーションの他の部分をより簡単にモックアウトできるようになり、応答方法を制御できるようになります。しかし、これはインターフェイスに合わせて設計することも意味します。

あなたがベストプラクティスについて尋ねたので、これはIMOの1つです。

次に、必要がない限りデータベースにアクセスしないでください。

カスケード削除を使用した外部キ​​ー関係など、特定の動作をテストする必要がある場合は、そのためのデータベース テストを作成することをお勧めしますが、通常、実際のデータベースには行かないことが最善です。同じデータベースを使用している場合、予想されるデータが変更される可能性があるため、テストが失敗する可能性があります。

編集:データベースユニットテストとは、t-sqlを使用してセットアップ、テスト、ティアダウンを行うように設計されているため、これを意味します。 http://msdn.microsoft.com/en-us/library/aa833233%28VS.80%29.aspx

于 2009-08-02T00:24:17.673 に答える