BOOK Preview

Microsoft Visual Studio 2005による
Webアプリケーションテスト技法

第4章 4.3 データアクセスクラスに対する単体機能テスト

マイクロソフトプレスの書籍紹介ページ
日経BPソフトプレスの書籍紹介ページ
書籍情報(書籍目次)のページ
2007/04/10
Page1 Page2 Page3

4.3.2 テストコードの記述方法

 先に述べたように、Visual Studio 2005上でのデータベースアプリケーション開発では、データコンポーネント機能(.xsdファイル)を活用すると、データアクセスクラス(DAC)やビジネスエンティティクラス(BEC)を簡単に作ることができる。このデータコンポーネント機能(.xsdファイル)を活用して開発されたモジュールを単体機能テストする際に重要なポイントは、「自動生成されたコードをテスト対象としない」という点である。例えば以下のような点に注意してテストを行う。

  • データアクセスクラス(DAC)に相当するテーブルアダプタクラスをテストする場合

    • 自動生成されたADO.NETのコードは、正しく動作して当然だと考える。例えば、そもそもデータベースに適切に接続できるか、クエリを発行できるか、データベースに接続できなかった場合に例外を返してくるか否か、構成設定ファイル内の接続文字列を適切に拾えるのか、といった低水準の動作(ライブラリやウィザードが責任を持ってくれるはずの部分)については検証しなくてよい。

    • しかし、自分で定義したSQL文が誤っている可能性は(他に比べて相対的に)高い。このため、定義したSQL文が期待通りに動作するか否かを中心として検証する。例えば、SELECT文は期待通りの列一覧を取得しているか、WHERE句には正しいフィルタリング条件を指定できているか、期待通りのJOIN処理が行われるか、などを検証するようなテストメソッドを書く。

    • ただし、partial機能を利用してテーブルアダプタクラスを拡張した場合には、各自が記述したコードに対する単体機能テストが必要になる。

  • ビジネスエンティティコンポーネント(BEC)に相当する型付きデータセットクラスをテストする場合

    • 基本的に、型付きデータセットはウィザードが自動生成するものである。よって検証対象としなくてよい。

    • 自動生成されたデータセットに加工を加えた場合(例えばExpression列を追加したりリレーションシップを追加したりした場合)には、それらが正しく定義できているかを検証するようなテストメソッドを記述する。

 上記の解説をまとめると、図4-24のようになる。

図 4-24 データコンポーネント機能(.xsdファイル)を使った場合のDACとBECのテスト対象部分

 テスト対象とすべき部分がはっきりしたら、あとはこれらをテストするためのテストメソッドを記述していけばよい。この際、参照系データアクセス処理をテストする場合と更新系データアクセス処理を記述する場合とで注意すべき点が異なる。これについて以下に簡単にまとめる。

A.参照系データアクセス処理をテストする場合

 基本的には、テーブルアダプタ上のメソッドを利用し、正しくデータが取得されたか否かをAssertクラスにより検証すればよい。サンプルコードをリスト4-10に示す。

■ C#の場合

public class AuthorsDataSetTest
{
  [TestMethod]
  public void GetDataByTopNormalTest()
  {
    authorsTableAdapter ta = new authorsTableAdapter();
    AuthorsDataSet.authorsDataTable dt = ta.GetDataByTop(5);
    Assert.AreEqual(5, dt.Count);
    Assert.AreEqual("Dean", dt[4].au_fname);
  }

  // partialクラス上に定義されたメソッドもテストする
  [TestMethod]
  [ExpectedException(typeof(ArgumentException))]
  public void GetDataByTopNgNumberTest()
  {
    authorsTableAdapter ta = new authorsTableAdapter();
    AuthorsDataSet.authorsDataTable dt = ta.GetDataByTop(-10);
  }
}
■ VBの場合

<TestClass()> _
Public Class AuthorsDataSetTest

  <TestMethod()> _
  Public Sub GetDataByTopNormalTest()
    Dim ta As authorsTableAdapter = New authorsTableAdapter()
    Dim dt As AuthorsDataSet.authorsDataTable = ta.GetDataByTopOrderByAuId(5)
    Assert.AreEqual(5, dt.Count)
    Assert.AreEqual("Dean", dt(4).au_fname)
  End Sub

  ' partial クラス上に定義されたメソッドもテストする
  <TestMethod()> _
  <ExpectedException(GetType(ArgumentException))> _
  Public Sub GetDataByTopNgNumberTest()
    Dim ta As authorsTableAdapter = New authorsTableAdapter()
    Dim dt As AuthorsDataSet.authorsDataTable = ta.GetDataByTop(-10)
  End Sub

End Class
リスト 4-10 参照系データアクセス処理の単体機能テスト

 データアクセスクラスのテストを行う場合には、ロックヒントつきクエリ*97のロックヒント動作に関する単体機能テストは省略することをお奨めする。単体機能テストでは「自分が書いたSQLクエリの動作を検証する」ことを目的とするので、厳密な意味では、指定したロックヒント通りにロックが獲得されることを確認することが望ましい。しかし、現実的にはこの確認作業を自動化することはかなり厄介である。このため、データアクセスクラスのテストに関しては、SQL文の基本的な動作や異常パラメータ値に対する振る舞いなどを中心に実施するとよいだろう。

*97 UPDLOCKロックヒントやREADCOMMITTEDロックヒントなど。ロックヒントに関する詳細は、『.NETエンタープライズWebアプリケーション開発技術大全Vol.5』の「第1部 短時間トランザクション処理」を参照のこと。

 なお、一般にUPDLOCKロックヒントなどの同時実行制御に関するロックヒントは、短時間トランザクション制御のために利用される。このようなロックヒントは、単体で検証するよりも、後述するビジネスロジッククラスに対する単体機能テストの負荷テストの中で検証した方がより効果的なテストができることが多い(図4-25)。詳細については、「4.4 ビジネスロジッククラスに対する単体機能テスト」の中で解説する。

図 4-25 ロックヒントなどの同時実行制御に関連する単体機能テストの実施方法

B.更新系データアクセス処理をテストする場合

 INSERT処理やUPDATE処理といった更新系データアクセス処理をテストする場合には、これらの処理がテスト用データを破壊してしまう点に注意が必要である。一般に、テストメソッドの実行順序は保証されていないため*98、どのような順序でテストメソッドが実行されても構わないように、各テストメソッドの終了時にはデータを元の状態に復元することが望ましい。

*98 処理順序を保証したテストを行いたい場合には、順序指定テストと呼ばれる機能を利用する。詳細については「4.8.2 汎用テストと順序指定テスト」を参照のこと。

 これを実現するには、.NET Framework 2.0の新機能であるSystem.Transactions機能(自動トランザクション機能)を活用するとよいだろう*99。リスト4-11に示すように、テストコード全体をTransactionScopeオブジェクトのusingブロックで囲み、テスト終了後にトランザクションコミットせずにスコープを抜ける。このようにすると自動トランザクションがロールバックされ、テスト用データベース内のデータが元の状態に戻る。

*99 自動トランザクション機能の詳細については、『Microsoft Visual Studio 2005によるWebアプリケーション構築技法』 の「7.7.3 自動トランザクション制御方式」を参照のこと。
 
■ C#の場合

[TestClass]
public class AuthorsDataSetTest
{
  [TestMethod]
  public void UpdateContractByStateTest()
  {
    // テストケース実施後にデータベースをロールバックするための自動トランザクション
     using (TransactionScope scope =
new TransactionScope(TransactionScopeOption.RequiresNew))
    {
      authorsTableAdapter ta = new authorsTableAdapter();
      int affectedRows = ta.UpdateContractByState("CA");
      Assert.AreEqual(15, affectedRows);
      // データが正しく更新されているかをピックアップして確認
      AuthorsDataSet.authorsDataTable dt2 =
        ta.GetDataByAuIdWithUpdlock("213-46-8915");
      Assert.AreEqual(false, dt2[0].contract);
    }
  }
}
■ VBの場合

<TestClass()> _
Public Class AuthorsDataSetTest

  <TestMethod()> _
  Public Sub UpdateContractByStateTest()
    ' テストケース実施後にデータベースをロールバックするための自動トランザクション
    Using scope As TransactionScope =
New TransactionScope(TransactionScopeOption.RequiresNew)
      Dim ta As authorsTableAdapter = New authorsTableAdapter()
      Dim dt As AuthorsDataSet.authorsDataTable = ta.GetDataByAuIdWithUpdlock("213-46-8915")
      Dim contract As Boolean = dt(0).contract
      Dim affectedRows As Integer = ta.SetNewContractByAuId(False, "213-46-8915")
      Assert.AreEqual(1, affectedRows)
      ' データが正しく更新されているかをピックアップして確認
      Dim dt2 As AuthorsDataSet.authorsDataTable =
ta.GetDataByAuIdWithUpdlock("213-46-8915")
      Assert.AreEqual(False, dt2(0).contract)
    End Using
  End Sub

End Class
リスト 4-11 更新系データアクセス処理の単体機能テスト
 

 INDEX
  Microsoft Visual Studio 2005によるWebアプリケーションテスト技法
  第4章 4.3 データアクセスクラスに対する単体機能テスト
    1. テスト用データベースの準備方法
  2. テストコードの記述方法
    3. テストの初期化処理と終了処理
 
インデックス・ページヘ  「BOOK Preview」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間