なか日記

一度きりの人生、楽しく生きよう。

MSTestでパラメータ化テストを行う

この前買った「JUnit実践入門 ~体系的に学ぶユニットテストの技法 (WEB+DB PRESS plus)」の演習問題を何となくMSTestを使ってやってみている。

19.5の消費税計算クラスで、「あ~、NUnitならTestCaseAttributeを使って簡単にパラメータ化テストができるのになぁ」と思いながらググってると、@さんの「JUnit実践入門 MSTest用パッチ #TddAdventJp - 亀岡的プログラマ日記」に行き着いた*1

そして改めて知った。@さんのChaining Assertionでできることを…*2

で、リファレンスを見ながら実装したテストがこれ

[TestClass]
public class ConsumptionTaxTest
{
    public TestContext TestContext { get; set; }

    [TestMethod]
    [TestCase(5, 100, 105)]
    [TestCase(5, 3000, 3150)]
    [TestCase(10, 50, 55)]
    [TestCase(5, 50, 52)]
    [TestCase(3, 50, 51)]
    public void テスト()
    {
        TestContext.Run((int taxRate, int price, int expected) =>
                        {
                            var sut = new ConsumptionTax(taxRate);
                            sut.Apply(price).Is(expected);
                        });
    }
}

ふむふむと見てたんだけど、TestContextのプロパティを作る意味がわからない!

Chaining Assertionの該当ソースを見ても理由はよくわからず…

/// <summary>Run Parameterized Test marked by TestCase Attribute.</summary>
public static void Run<T1, T2, T3>(this TestContext context, Action<T1, T2, T3> assertion)
{
    var type = Assembly.GetCallingAssembly().GetType(context.FullyQualifiedTestClassName);
    foreach (var parameters in GetParameters(type, context.TestName))
    {
        assertion(
            (T1)parameters[0],
            (T2)parameters[1],
            (T3)parameters[2]
            );
    }
}

そして、ググってたら同じような疑問を持った人が居た。

なるほど、「拡張メソッド (C# プログラミング ガイド)」を見ると、そもそも拡張メソッドは

拡張メソッドは特別な種類の静的メソッドですが、拡張された型のインスタンス メソッドのように呼び出します。 ということで、あくまでインスタンスに対してメソッドを追加する感じなのね。

でも、プロパティを介すことで明示的にインスタンスを生成しなくても呼び出せちゃう。つまり、静的なメソッドっぽく使えると。

なるほどなるほど。と、正しい理解かどうかわからないけど、納得した。

*1:このエントリのお世話になるのは実に3度目

*2:前にも見たのに忘れてた