Chaining Assertion for MSTest

MSTest用の拡張メソッド集をCodePlexと、そしてNuGet(idはChainingAssertionです)にリリースしました。ライブラリといってもたった数百行(うち300行が自動生成)の、csファイル一つです。NuGet経由でも.csが一個配置されるだけという軽量軽快さ。中心となるのはIsというTへの拡張メソッドで、これはAssert.EqualとAssert.IsTrue(pred)とCollectionAsert.AreEqualを、一つのメソッドだけで表現します。単純なものですが、それだけなのに驚くほどテストが書きやすくなります。まずは例を。

// 全てのオブジェクトに.Isという拡張メソッドが追加されていて、3つのオーバーロードがあります
 
// Assert.AreEqualと等しい
Math.Pow(5, 2).Is(25);
 
// 条件式によるAssert.IsTrueをラムダ式で
"foobar".Is(s => s.StartsWith("foo") && s.EndsWith("bar"));
 
// コレクションの等値比較は可変長引数でダイレクトに書ける
Enumerable.Range(1, 5).Is(1, 2, 3, 4, 5);

以前どこかで見たような?はい。ベースはテストを簡単にするほんの少しの拡張メソッドで書いたものです。それを元に若干ブラッシュアップしています。ラムダ式によるAssert時のエラーメッセージが、非常に分かりやすくなりました。

前はFuncだったのですが、Expressionで受けるようにしたので、情報が取れるようになったらからです。それと渡ってくる値に関しても表示。これで、情報が足りなくてイライラってのがなくなって、かなり書きやすくなりました。

ところでnullに関してはIsNullとIsNotNullというメソッドに分けました。あまり増やしたくはないので、入れるか悩んだんですけどね。x => x == null でもいいのだし。

TestCase/Run

以前書いた時もNUnit風のTestCaseの再現を試みていたのですが、今回は抜本的に作り替えてリベンジしました。再現度(それっぽい度)は相当上がっています。といっても、目的は再現度を上げることじゃあないですね、大丈夫です、これにより、遥かに使いやすく実用的になりました。

[TestClass]
public class UnitTest
{
    public TestContext TestContext { get; set; }
 
    [TestMethod]
    [TestCase(1, 2, 3)]
    [TestCase(10, 20, 30)]
    [TestCase(100, 200, 300)]
    public void TestMethod2()
    {
        TestContext.Run((int x, int y, int z) =>
        {
            (x + y).Is(z);
            (x + y + z).Is(i => i < 1000);
        });
    }
}

TestContextへの拡張メソッドにRunというのが仕込んであって、それとTestCase属性が連動して、パラメータ指定のテストが行えるようになっています。TestCaseSource属性もありますよ?

[TestMethod]
[TestCaseSource("toaruSource")]
public void TestTestCaseSource()
{
    TestContext.Run((int x, int y, string z) =>
    {
        string.Concat(x, y).Is(z);
    });
}
 
public static object[] toaruSource = new[]
{
    new object[] {1, 1, "11"},
    new object[] {5, 3, "53"},
    new object[] {9, 4, "94"}
};

何でTestContextへの拡張メソッドという形をとっているかというと、TestContextから実行中クラス名とメソッド名が簡単に取れるから、です。この二つさえ分かれば、あとはリフレクション+LINQでやり放題ですからねー。クラス名が取れるTestContext.FullyQualifiedTestClassNameは、どうやらVS2010からの追加なようで、ナイス追加。VS2008からTest周りは何も進化しなくてNUnitと比べるとアレもコレも、な感じなわけですが、地味に改良はされていたんですね。いや、誰が嬉しいんだよって話ですが、私は大変嬉しかったです。

テストケースとして分けられないので、非常にオマケ的ではあるんですが、大変お手軽なので無いよりは嬉しいかな、と。

まとめ

Assert.HogeHogeの楽しくなさは異常。本当にダルい。かといって、英語的表現を目指した流れるようなインターフェイスは爆笑ものの滑稽さ。ああいうのをDSLと言うのは止めましょうぜってぐらいの。まあ、そんなわけで、これを使うと結構快適に書けます。Isの一つ一つは馬鹿みたいに単純なたった一行のメソッドなんですが、それだけなのに、全然違うんですよね。

というわけでまあ、楽しいテスト生活を!あと、最近は自動化テストなPexや、それと絡むCodeContractsを触っているので、それらについて近いうちに書けたらと思っています。

Comment (2)

kenjun : (08/05 15:25)

お世話になっております。
DynamicAccessorを使ってprivateメソッドのテストをするにあたり
正常に完了できないケースを発見しましたので解決方法をご教授願います。

そのケースとはoutパラメータ(またはrefパラメータ)をメソッドが持つ場合です。
実施すると、MSTest.csの770行目でエラーが発生します。

neuecc : (08/11 13:08)

おやや、out, refというのは試したことなかったですね、なるほど……。
解決方法という点では現状は未対応ということになってしまいますが、うーん、それは直したいですね

Name
WebSite(option)
Comment

Trackback(1) | http://neue.cc/2011/02/23_304.html/trackback

Twitter Trackbacks for neue cc - Chaining Assertion for MSTest [neue.cc] on Topsy.com : (02/23 00:58)

[…] neue cc - Chaining Assertion for MSTest neue.cc/2011/02/23_304.html – view page – cached […]

Search/Archive

Category

Profile


Yoshifumi Kawai
Microsoft MVP for Developer Technologies(C#)

April 2011
|
July 2021

Twitter:@neuecc
GitHub:neuecc
ils@neue.cc