16
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

NUnitのテストケースを動的に定義する

Last updated at Posted at 2015-10-19

TestCase属性

NUnitはテストケースをTestCaseという属性で書くことができます。

NUnitのサイトより抜粋

[TestCase(12,3,4)]
[TestCase(12,2,6)]
[TestCase(12,4,3)]
public void DivideTest(int n, int d, int q)
{
  Assert.AreEqual( q, n / d );
}

でも、テストケースが何千とある場合、実際のテストメソッドがテストケースに埋もれてしまいます。ですのでテストケースは別ファイルに書き出したいですね。

TestCaseSourceAttribute属性

TestCaseAttributeを使うと、変数に格納されたテストデータをテストケースとして使うことができます。

NUnitのサイトより抜粋

[TestCaseSourceAttribute("DivideCases")]
public void DivideTest(int n, int d, int q)
{
    Assert.AreEqual( q, n / d );
}

static object[] DivideCases =
{
    new object[] { 12, 3, 4 },
    new object[] { 12, 2, 6 },
    new object[] { 12, 4, 3 } 
};

メソッドの戻り値もOK

[TestCaseSourceAttribute("DivideCases")]
public void DivideTest(int n, int d, int q)
{
    Assert.AreEqual( q, n / d );
}

static object[][] DivideCases ()
{
    return new object[][] {
        new object[] { 12, 3, 4 },
        new object[] { 12, 2, 6 },
        new object[] { 12, 4, 3 }
    };
}

クラスも指定可、その場合はTestCaseSourceAttribute(Type sourceType, string sourceName)を使います。

public class MyFactoryClass
{
    public static object[][] DivideCases()
    {
        return new object[][] {
            new object[] { 12,  3,  4 },
            new object[] { 12,  2,  6 },
            new object[] { 12,  4,  3 },
        };
    }
}

[TestFixture]
class Program
{
    [TestCaseSourceAttribute(typeof(MyFactoryClass), "DivideCases")]
    public void DivideTest(int n, int d, int q)
    {
        Assert.AreEqual(q, n / d );
    }
}

応用

メソッド内で外部ファイルを読み出してそのデータに伴ってテストデータを生成すれば、動的に生成可能です。今回はJsonが記述されているファイルを読んでます。DynamicJsonは整数が浮動小数点でパースされるので、テスト定義クラス内でキャストしてます。

using System;
using System.Collections.Generic;
using NUnit.Framework;
using Codeplex.Data;
using System.IO;

namespace Test_Nunit1
{
    // テスト対象のクラス
    class Calculator
    {
        public Calculator()
        {
        }

        public int add(int a, int b)
        {
            return a + b;
        }
    }

    // テストケース生成用のクラス
    public class MyFactoryClass
    {
        public static object[][] BaseTestCase(string filename)
        {
            var test_case_list = new List<object[]>();

            var test_case_txt = File.ReadAllText(filename);
            foreach (var testcase in DynamicJson.Parse(test_case_txt))
            {
                test_case_list.Add((object[])testcase);
            }

            return test_case_list.ToArray();
        }

        public static object[][] AddTestCase()
        {
            return BaseTestCase("AddTestCase.txt");
        }
    }

    // テスト定義クラス
    [TestFixture]
    class Program
    {
        [TestCaseSourceAttribute(typeof(MyFactoryClass), "AddTestCase")]
        public void 足し算のテスト(double a, double b, double c)
        {
            var test = new Calculator();
            Assert.AreEqual((int)c, test.add((int)a, (int)b));
        }
    }
}
AddTestCase.txt
[
  [1,2,3],
  [2,2,4],
  [3,4,7],
  [5,6,11],
  [7,8,15],
  [7,9,16],
  [100,200,300]
]
16
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?