MSTestはパラメトリックテストの解決策をサポートしていない

7005 ワード

以前のプロジェクトではユニットテストにNUnitを使用していましたが、今回は新しいプロジェクトを行い、担当者がMsTestを統一するように要求しました.理由はMsTestがVisual Studioに内蔵されているからです.使ってください.私は何の意見もありません.しかし、2日間で大きな問題を発見しました.MsTestはパラメータ化テストをサポートしていません(行テストと呼ばれるものもあります).
 
パラメトリックテストとは?簡単に言えば,同じ論理であり,入力パラメータによって異なる結果を与える.パラメータが異なるだけなので、テストを何度も書くことは望んでいませんが、各パラメータのテストを独立したテスト例にしたいと思っています.例えば、数値*2を計算する数学的な計算方法があると仮定し、この方法が正数、負数、0に対して通過していることを証明したい.NUnitでは、TestCaseAttributeを使用してテストのパラメータを指定できます.
[TestCase(100, 200)]
[TestCase(0, 0)]
[TestCase(-123, -246)]
public void TestDouble(int value, int result)
{
    Assert.AreEqual(result, Calc.Double(value));
}

 
しかしMsTestには類似機能のAttributeは存在しない.どうしようかな?最も簡単で乱暴な方法はもちろんループを書いてパラメータを提供することです.しかし、これは私が望んでいる結果ではありません.一つは、ループを書くコードが少し意味がありません.さらに重要なのは,ループは全体的なテスト例としてしか実行できず,エラーが発生した場合,自分で情報を書かなければどのパラメータがエラーであるかを見分けることができないことである.
 
ネットで探してみると、似たような質問をする人が多いことに気づきました.基本的に答えは以下のいくつかの案に集中しています.
1.VS 2012 Update 1以降はDataRow属性が提供されているが、Windows Store Appsでのみ使用可能である.(個人的には奇抜だと思いますが、1つのテスト機能でStoreユーザーを優遇する必要はありますか?)とにかく私たちが作ったのは普通のクラスライブラリで、この方法は適用されません.
2.DataSourceAttributeでは、文書という表記に従って、データソースとしてOleDBデータソース、XMLまたはCSV形式のファイルを提供することができます.簡単なパラメータテストという案は本当に重すぎて、定義通りに外部ファイルやデータベースを使用したユニットテストはユニットテストと言えるのでしょうか.
3.テストを拡張するには、PostSharpエンハンスコードを使用します.この案は大体見てもあきらめたが、PostSharpは比較的非主流の技術であり、それを使うとコンパイルプロセスの複雑さが明らかに増加し、持続的な統合にも少し友好的ではない.
4.MsTestオブジェクトモデルに従って、いくつかの拡張属性を書きます.正直に言うと、ソリューションを探す前に、私はこの道を行くべきだと心の中で判断しました.そして、ネットワークの例に従って本当にいくつかの拡張属性を書いてテストしました.コンパイルは正常ですが、テストは死活して実行できません.さらに詳しく見ると、Visual Studioで拡張テストを実行するには、いくつかのレジストリ項目を変更する必要がありました.よし、私たちの開発チームは十数人がレジストリを振り回してこそテストできるので、仲間たちを喜ばせないで一緒に游ぶことができます.とにかくこの案もPass.
 
見てみれば、満足できる方法はないようだが、唯一できるのはDataSourceだけだ.もちろん私はデータベースのような重量級のデータソースを使うことはありません.それはユニットテストにとって完全に高射砲で蚊を撃ちます.ファイルを使うと、ポピュラーな敏捷な開発理念からも問題がありますが、ファイルは比較的コントロールしやすいです.そこでXMLファイルでテストして合格しましたが、いくつかの小さな穴に注意して、ここに記録しておきます.
 
コードの例は次のとおりです.簡単です.説明しません.
[TestClass]
[DeploymentItem(@"Fixtures\add.xml")]
public class UnitTest1
{
    public TestContext TestContext { get; set; }

    [TestMethod]
    [DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML",
        @"|DataDirectory|\Fixtures\add.xml",
        "row",
        DataAccessMethod.Sequential)]
    public void TestMethod1()
    {
        int a = Convert.ToInt32(TestContext.DataRow["a"]);
        int b = Convert.ToInt32(TestContext.DataRow["b"]);
        int expected = Convert.ToInt32(TestContext.DataRow["expected"]);
        var result = new Class1().Add(a, b);
        Assert.AreEqual(expected, result);
    }
}

 
テスト用XMLファイル:
<rows>
    <row a="1" b="2" expected="3" />
    <row a="2" b="-1" expected="-1" />
    <row a="3" b="0" expected="3" />
</rows>

 
テストにはいくつかの注意点があります.
  • テストクラスにTestContext属性を追加する必要があります.
  • XMLファイルコンパイルプロパティのCopy to output directoryは、Copy alwaysまたはCopy if newerに設定する必要があります.
  • リモート・サーバでのテストに成功するには(CIサーバなど)、このファイルがプログラム・セットとともにテスト場所に配備されることを示すDeployItemの寸法を付ける必要があります.
  • DataSourceの2番目のパラメータでDataDirectoryとは何か、MSDNではデータベースのみを例に、XML/CSVの場合は説明していません.結果的にプログラム出力の位置であるはずです.

  •  
    結果は利用可能であるが,正直に言うと,このようなテストコードは体感的にはNUnitほど簡単で優雅ではない.マイクロソフトはVisual Studioのテストインタフェースをそんなに複雑にするよりも、MsTestに実用的なコア機能を追加したほうがいいと思います.もちろんこれらは余談です.