VS2005環境でのNAgile - 駄目じゃんMSTestのClassInitializeアトリビュート (>_<)

リレーションのある場合の型付DataTableでは行追加のメソッドではリレーションの親行のDataRowのインスタンスを渡さなくてはいけないようなメソッドシグニチャになっている。

例えばこんな感じ。

[System.Diagnostics.DebuggerNonUserCodeAttribute()]
public BooksRow AddBooksRow(string Isbn, string Title, string Author, string Translator, 
 CategoriesRow parentCategoriesRowByBooks_Categories) {
 BooksRow rowBooksRow = ((BooksRow)(this.NewRow()));
 rowBooksRow.ItemArray = new object[] {
  Isbn, 
  Title, 
  Author,
  Translator,
  parentCategoriesRowByBooks_Categories[0]};
 this.Rows.Add(rowBooksRow);
 return rowBooksRow;
}

このDataTableに対するTableAdapterのテストを書こうとすると、参照整合性規則のためにテストデータとして親テーブルのデータも予め準備しておいてやる必要がある。そこでテストクラスの全てのテストの開始前にテストDBにテストデータをInsertし、全てのテストの終了後にテストデータをDeleteしようと考えた。

#型付されたDataSetではテスト容易性を考慮して参照整合性規則を用いずに制約だけのリレーションシップを適用する方が望ましいと思うが、今回は学習のために参照整合性規則を適用したリレーションシップを適用した。

まず思い浮かぶのがNUnitのTestFixtureSetUp/TestFixtureTearDownアトリビュートだ。肝心のMSTestにもClassInitialize/ClassCleanupアトリビュートというのが準備されているのでこれを使用することにした。

TestDriven.NETでテストを実行している間は問題なくテストが成功。ところがVSのIDEで全てのテストを実行するとさっきまで成功していたテストが失敗している。

失敗したテストを見てみると、現在のDataTableの親Tableに対するTableAdapterのテストでプライマリキー違反が発生している。

どうやら現在のテストクラスのテストが全て終わってもClassCleanupが走っていないようだ。結局のところClassCleanupアトリビュートのついたメソッドが実行されるタイミングは制御できないんじゃないかな。staticだし。

ここ見て気づいた。ClassInitialize/ClassCleanupアトリビュートは全てのテストの実行前と実行後か。AssemblyInitialize/AssemblyCleanupが正しかったのかな。

#あとで書いた。

上記のドキュメントではAssemblyInitializeとClassInitialize、AssemblyCleanupとClassCleanupの説明がそれぞれ逆になってるんだな。あー紛らわしい。

結局のところ、やはりClassCleanupは各テストクラスに含まれているテストが全て実行された後に走るのではなくて、テストアセンブリに含まれているテストが全て実行された後に走っている。これじゃあAssemblyCleanupと変わらない。

実行順序はこのような感じ

[TestClass]
public class SomeTest
{
  [AssemblyInitialize]
  public static void MyAssemblyInitialize(TestContext testContext)
  {
    // 1
  }

  [AssemblyCleanup]
  public static void MyAssemblyCleanup()
  {
    // 8
  }

  [ClassInitialize]
  public static void MyClassInitialize(TestContext testContext)
  {
    // 2
  }

  [ClassCleanup]
  public static void MyClassCleanup()
  {
    // 6
  }

  [TestMethod]
  public void SomeTestMethod()
  {
    // 3
  }
}

[TestClass]
public class OtherTest
{
  [ClassInitialize]
  public static void MyClassInitialize(TestContext testContext)
  {
    // 4
  }

  [ClassCleanup]
  public static void MyClassCleanup()
  {
    // 7
  }

  [TestMethod]
  public void OtherTestMethod()
  {
    // 5
  }
}