C#でのテスト

単体テストの作成

対象とするクラスにTestClass属性を、メソッドにTestMethod属性を指定します。

public class MyClass
{
    static public int Method()
    {
        return 0;
    }
}

[TestClass]
public class UnitTest
{
    [TestMethod]
    public void TestMethod1
    {
        int a = MyClass.Method();

        Assert.AreEqual(1, a);
        // Assert.AreEqual に失敗しました。<1> が必要ですが、<0> が指定されました。
    }
}

関連するクラス

クラス テスト対象
Assert 一般
CollectionAssert コレクション
StringAssert 文字列
AssertFailedException 例外
AssertInconclusiveException  
UnitTestAssertException  
Microsoft.VisualStudio.TestTools.UnitTesting 名前空間 | MSDN 単体テスト フレームワーク | MSDN

属性

  • TestClassAttribute … このクラスが、テスト対象であることを示す
  • TestMethodAttribute … このメソッドが、テスト対象であることを示す
  • ExpectedExceptionAttribute … このメソッドが、例外を投げることを期待する

一般的なテスト … Assertクラス

検証内容 メソッド
肯定 否定
同一の値であるか AreEqual() AreNotEqual()
同一のオブジェクトであるか AreSame() AreNotSame()
指定の型であるか IsInstanceOfType() IsNotInstanceOfType()
trueであるか IsTrue() IsFlase()
nullであるか IsNull() IsNotNull()
メソッド - Assert クラス (Microsoft.VisualStudio.TestTools.UnitTesting) | MSDN

このAssertクラスは、DebugクラスのAssert()メソッドとは異なります。

コレクションの検証にはCollectionAssert、文字列の特殊な検証にはStringAssertを用います。

AreEqual()メソッド

Assert.AreEqual メソッド (Microsoft.VisualStudio.TestTools.UnitTesting) | MSDNにあるように、多数のオーバーロードがあります。

2つのオブジェクトが、同一であることを検証

public static void AreEqual(
    Object expected, // テストで予測するオブジェクト
    Object actual    // テストで生成したオブジェクト
)
Assert.AreEqual メソッド (Object, Object) (Microsoft.VisualStudio.TestTools.UnitTesting) | MSDN

浮動小数点数は演算時に丸めによって誤差が生じるため、精度を指定できるAreEqual(Double, Double, Double)の形式で検証します。

2つのジェネリック型データが、同一であることを検証

public static void AreEqual<T>(
    T expected, // テストで予測するジェネリック型データ
    T actual    // テストで生成したジェネリック型データ
)
Assert.AreEqual(T) メソッド (T, T) (Microsoft.VisualStudio.TestTools.UnitTesting) | MSDN

2つの倍精度浮動小数点数が、指定された精度内にあることを検証

public static void AreEqual(
    double expected, // テストで予測する値
    double actual,   // テストで生成した値
    double delta     // 精度
)
Assert.AreEqual メソッド (Double, Double, Double) (Microsoft.VisualStudio.TestTools.UnitTesting) | MSDN

2つの文字列が、同一であることを検証

public static void AreEqual(
    string expected, // テストで予測する値
    string actual,   // テストで生成した値
    bool ignoreCase  // trueならば、大文字/小文字を区別しない
)
Assert.AreEqual メソッド (String, String, Boolean) (Microsoft.VisualStudio.TestTools.UnitTesting) | MSDN

コレクションのテスト … CollectionAssertクラス

検証内容 メソッド
肯定 否定
同一であるか (同じ値の要素が同じ順番で同じ数ある) AreEqual() AreNotEqual()
等価であるか (同じ値の要素が同じ数ある) AreEquivalent() AreNotEquivalent()
指定の要素を含むか Contains() DoesNotContain()
別のコレクションのサブセット (部分集合) であるか IsSubsetOf() IsNotSubsetOf()
検証内容 メソッド
すべての要素が指定の型であるか AllItemsAreInstancesOfType()
すべての要素がnullでない AllItemsAreNotNull()
すべての要素が一意であるか (同一の要素がない) AllItemsAreUnique()
メソッド - CollectionAssert クラス (Microsoft.VisualStudio.TestTools.UnitTesting) | MSDN

文字列のテスト … StringAssertクラス

単純に等しいかどうか検証するだけならば、AssertクラスのAreEqual()を用います。

検証方法 メソッド
肯定 否定
指定の正規表現に一致するか Matches() DoesNotMatch()
検証方法 メソッド
指定の文字列を含むか Contains()
指定の文字列で始まるか StartsWith()
指定の文字列で終わるか EndsWith()
メソッド - StringAssert クラス (Microsoft.VisualStudio.TestTools.UnitTesting) | MSDN

例外のテスト … ExpectedExceptionAttribute

例外の検証には、ExpectedExceptionAttribute属性に指定します。ExpectedExceptionAttribute クラス (Microsoft.VisualStudio.TestTools.UnitTesting) | MSDN

この属性が付けられたメソッドでは、指定の例外が投げられないとテストに失敗します。

[TestMethod]
[ExpectedException(typeof(System.Exception))]
public void TestMethod1()
{
}

たとえばこの場合は、「テスト メソッド TestMethod1 は例外をスローしませんでした。」「テスト メソッドで定義されている属性 ExpectedExceptionAttribute で例外が予期されていました。」として失敗します。

[TestMethod]
[ExpectedException(typeof(System.Exception))]
public void TestMethod2()
{
    throw new System.Exception();
}

一方で例外が投げられれば、テストに成功します。このとき例外はメソッドの外に投げられる必要があるため、メソッド内で捕捉しては失敗となります。

[TestMethod]
[ExpectedException(typeof(System.Exception))]
public void TestMethod3()
{
    try
    {
        throw new System.Exception();
    }
    catch (Exception) { }
}

また例外が投げられることを期待する処理は、テストメソッドの最後にします。さもなくばそれ以降の処理が評価されないまま、テストに成功してしまうことになります。

[TestMethod]
[ExpectedException(typeof(System.Exception))]
public void TestMethod2()
{
    throw new System.Exception();

    Assert.Fail(); // ここが評価されないまま、テストに成功する
}

テストの無効化 … IgnoreAttribute

Ignore属性をテストメソッドに追加することで、そのテストを一時的に無効にできます。

[TestMethod]
[Ignore]
public void TestMethod1()
{
}
IgnoreAttribute クラス (Microsoft.VisualStudio.TestTools.UnitTesting) | MSDN

無効化したテストを再び有効にするには、Ignore属性を削除するか、コメントアウトします。方法 : テストを無効または有効にする | MSDN

TestMethod属性を削除することでもテストを無効にできますが、それではテストの存在そのものが隠されてしまうため、Ignore属性を用いるようにします。

複数テストの有効・無効を一括して切り替えるには、#ifディレクティブでIgnore属性の指定を制御するか、TestCategory属性でテストをまとめます。c# - Ignore IgnoreAttribute - Stack Overflow

トラブル対処法

テストの終了後にSystem.InvalidOperationExceptionが発生し、「進行中のテストの実行がないので、テストの実行を取り消すことができません。(The cancelation of the test run is not possible as there is no test run which is in progress.)」と報告されることがあります。これはデバッグの設定で[マイ コードのみを有効にする]を有効にすることで解決できます。visual studio 2012 - Unit Test: The cancelation of the test run is not possible as there is no test run which is in progress - Stack Overflow

トラブル対処法

MSDN (Microsoft Developer Network) から検索