NUnit 2.5

NUnit 2.5がリリースされました。

リリースノートを見てみると、面白そうな機能が追加されているようなので、ちょっと遊んでみました。
(2009年5月26日追記:Release Notesには「Release Candidate」と書いてありますが、ちゃんと「Final Release」が公開されています。)

パラメータ化されたテスト

TestCase

テストケースをAttributeで書くことができます。
たとえば、以下のように書くと、引数を変えて3回のテストが実行されます。

[TestFixture]
public class AttributeTestSample
{
    [TestCase(1, 2, 3)]
    [TestCase(10, 20, 30)]
    [TestCase(10, 10, 20)]
    public void TestCaseSample(int x, int y, int z)
    {
        Assert.That(x + y, Is.EqualTo(z));
    }
}
TestCaseSource

TestCaseは便利なのですが、どうやら引数は3つまでしか指定できないようです。
TestCaseSourceを使うと、テストケースをオブジェクトで指定できます。

[TestFixture]
public class AttributeTestSample
{
    [Test, TestCaseSource("TestData")]
    public void TestCaseSourceSample(int x, int y, int z, int result)
    {
        Assert.That(x + y + z, Is.EqualTo(result));
    }

    static object[] TestData =
       {
           new object[] { 1, 2, 3, 6 },
           new object[] { 10, 20, 30, 60 },
           new object[] { 10, 10, 10, 30 }
       };
}
Values

Valuesを使うと組み合わせテストを実行してくれます。
たとえば、以下のように書くと、xが1〜6,yが1〜6の組み合わせでテストメソッドが実行されます。

[TestFixture]
public class AttributeTestSample
{
    [Test]
    public void ValuesSample(
        [Values(1, 2, 3, 4, 5, 6)] int x,
        [Values(1, 2, 3, 4, 5, 6)] int y)
    {
        Assert.That(x * y, Is.EqualTo(x * y));
    }
}

実行結果はこんな感じ。

Combinatorial/Sequential/Pairwise

Valuesで指定した値の組み合わせ方法を指定することもできます。

たとえば、Valuesが(1,2,3)と(4,5,6)の場合、Combinatorialを指定すると(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)という組み合わせ、Sequentialを指定すると(1,4),(2,5),(3,6)という組み合わせでテストしてくれます。Pairwiseはまだ未実装っぽい。

Range/Random

指定した範囲の引数を順にテストしたり、ランダムでテストしたりできます。以下の例では、0〜10まで2刻みで引数を与えてくれます。

[TestFixture]
public class AttributeTestSample
{
    [Test]
    public void RangeSample([Range(0, 10, 2)] int x)
    {
        Assert.That(x % 2, Is.EqualTo(0));
    }
}
Theory

これは、JUnitではすでに取り入れられていた機能のようです。Datapointで指定した値が、Theoryで指定した条件を満たすかどうかをチェックしてくれます。
Assumeで事前条件、Assertで事後条件をチェックするようなのですが、いまいち使いどころが分かりません・・・

TestFixtureでの型パラメータ指定

generics型のテストクラスを作ることができます。
型パラメータはTypeArgsで指定して、その値はコンストラクタで受け取ることができます。

[TestFixture(1.0, 2, TypeArgs = new Type[] { typeof(double), typeof(int) })]
public class TypeArgsSample<T1, T2>
{
    T1 t1;
    T2 t2;

    public TypeArgsSample(T1 t1, T2 t2)
    {
        this.t1 = t1;
        this.t2 = t2;
    }

    [Test]
    public void TestArgs()
    {
        Assert.That(t1, Is.EqualTo(1.0));
        Assert.That(t2, Is.EqualTo(2));
    }
}

Constrainsts

Assert.Thatで評価する際に使えるものも増えています。

  • Is.InRange: 指定された範囲にあるかどうかをチェックします。
  • Has.Attribute: 指定された属性を持つかどうかチェックします。
  • Throws.Exception / Throws.Nothing: 例外が発生したかどうかチェックします。今まではExpectedExceptionでチェックする必要があり面倒だったのですが、これは便利ですね。
  • Is.Ordered: 指定した評価関数どおりにデータが並んでいるかどうかチェックします。
  • Is.SamePath / Is.SamePathOrUnder: パスをチェックします。

流れるようなインタフェース

EqualToの後ろにメソッドチェーンでどんどん条件を追加していけます。
以下の例では、値がPI±0.2の範囲に値が入っているかどうかチェックしています。

[TestFixture]
public class FluentInterfaceSample
{
    [Test]
    public void TestPI()
    {
        Assert.That(3.14, Is.EqualTo(Math.PI).Within(0.2)); // OK
        Assert.That(3.1, Is.EqualTo(Math.PI).Within(0.2)); // OK
        Assert.That(3, Is.EqualTo(Math.PI).Within(0.2)); // OK
        Assert.That(2.9, Is.EqualTo(Math.PI).Within(0.2)); // NG
    }
}

さらに、Withinの後ろにPercentとかDaysなどの単位もつけられます。
Withinの他にもAndやOr、IgnoreCase、Withなどが利用できるようです。

Asserts

DirectoryInfoのチェックや、例外チェック、Assert.IsInstanceOfのような型チェックなど、Assertの種類が増えています。

その他

  • Constraintsを追加するためのアドインが開発できます。
  • pNUnitという並行実行が可能なNUnitが追加されています。
  • アセンブリとネームスペースが1つにまとめられました。

使いみちの分からないものもあったりしますが、かなり機能がふえていますね。
個人的には、Values, Range, Throws.Exceptionあたりがうれしいです。