読者です 読者をやめる 読者になる 読者になる

いろいろ備忘録日記

主に .NET 絡みのメモを公開しています。

VS2008の単体テストにてテストデータを外部ファイルから設定する (Visual Studio, 単体テスト, CSV, XML)

C#

よく、ユニットテスト書くときに忘れるのでメモメモ。


Visual Studio 2008からProfessional版に搭載された単体テスト機能ですが
普通にユニットテストを作ると以下のようになります。



テスト対象メソッド

        public int Sum(int x, int y){
            return (x + y);
        }

自動作成されたテストメソッド

        /// <summary>
        ///Sum のテスト
        ///</summary>
        [TestMethod()]
        public void SumTest() {
            Program target = new Program(); // TODO: 適切な値に初期化してください
            int x = 0; // TODO: 適切な値に初期化してください
            int y = 0; // TODO: 適切な値に初期化してください
            int expected = 0; // TODO: 適切な値に初期化してください
            int actual;
            actual = target.Sum(x, y);
            Assert.AreEqual(expected, actual);
            Assert.Inconclusive("このテストメソッドの正確性を確認します。");
        }


後は、テストしたい値を設定して書き換えます。

        /// <summary>
        ///Sum のテスト
        ///</summary>
        [TestMethod()]
        public void SumTest() {
            Program target = new Program();
            int x = 1;
            int y = 2;
            int expected = 3;
            int actual;
            actual = target.Sum(x, y);
            Assert.AreEqual(expected, actual);            
        }


んで、テストしてめでたく成功したら次のテストへって感じですが、
いちいちいろんなデータのパターンをその都度テストメソッド作って
書いてたら大変です。


そういう時に、外部ファイルとしてテストデータを作成して
それをテストデータとして利用する方法があります。


やり方は以下の3通りあります。

  • データベースデータを利用する。
  • CSVファイルを利用する。
  • XMLファイルを利用する。


データベースを利用する方法は割愛します。
まずは、CSVから。


エディタやExcelなどを使ってCSVファイルを作成します。

x,y,answer
0,0,0
1,1,2
1,2,3
2,1,3
10,10,20

一行目に列名を付けておきます。これが後でテストの際に
データを取得する為の列名になります。


後は、これを以下の手順で設定します。

  1. メニューから テスト⇒ウィンドウ⇒テストリストエディタ を選択
  2. 該当のテストの行を右クリックしてプロパティ表示。
  3. データ接続文字列を選択して、CSVファイルで作成したCSVファイルを選択


すると、テストメソッドが以下の状態に変更されます。

        /// <summary>
        ///Sum のテスト
        ///</summary>
        [DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", "|DataDirectory|\\TestData.csv", "TestData#csv", DataAccessMethod.Sequential), DeploymentItem("TestProject1.Tests2\\TestData.csv"), TestMethod()]
        public void SumTest() {
            Program target = new Program();
            int x = 1;
            int y = 2;
            int expected = 3;
            int actual;
            actual = target.Sum(x, y);
            Assert.AreEqual(expected, actual);            
        }


属性が付加されました。
で、ここままでは、設定する前と同じですので、指定したテストデータからデータを取得できるように
する必要があります。


データを取得するには、以下のプロパティにアクセスします。

TestContext

TestContextはテストクラス上で以下のようにプロパティ設定されています。

        /// <summary>
        ///現在のテストの実行についての情報および機能を
        ///提供するテスト コンテキストを取得または設定します。
        ///</summary>
        public TestContext TestContext {
            get {
                return testContextInstance;
            }
            set {
                testContextInstance = value;
            }
        }


このオブジェクトのDataRowよりデータが取得できます。
テストメソッドをTestContext用に書き換えた版が以下です。

        /// <summary>
        ///Sum のテスト
        ///</summary>
        [DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", "|DataDirectory|\\TestData.csv", "TestData#csv", DataAccessMethod.Sequential), DeploymentItem("TestProject1.Tests2\\TestData.csv"), TestMethod()]
        public void SumTest() {
            Program target = new Program();
            int x = int.Parse(TestContext.DataRow["x"].ToString());
            int y = int.Parse(TestContext.DataRow["y"].ToString());
            int expected = int.Parse(TestContext.DataRow["answer"].ToString());
            int actual;
            actual = target.Sum(x, y);
            Assert.AreEqual(expected, actual);            
        }


これで、テストを実行するとテストデータファイルからデータが読み込まれ
テストが行われます。



後、XMLでの設定も出来ます。
以下のようにしてXMLファイルを記述します。

<?xml version="1.0" encoindg="utf-8"?>
<TestData>
    <Data>
        <x>1</x>
        <y>2</y>
        <answer>3</answer>
    </Data>
    <Data>
        <x>2</x>
        <y>3</y>
        <answer>5</answer>
    </Data>
</TestData>


要素の書き方は自由みたいです。見たまんまですが
今度は要素名が列名となります。

設定方法はCSVの場合と同じです。
データの取得方法も同じです。


TestContextには、他にも時間を計るメソッドがあったりしますので
込み入ったテストを作成する際には、便利です。



補足:
DataRowクラスには、Field拡張メソッドがあるので

System.Data.DataSetExtensions.dll

を参照設定して、

using System.Data;

しておくと、テストメソッドが以下のように書けます。

        /// <summary>
        ///Sum のテスト
        ///</summary>
        [DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", "|DataDirectory|\\TestData.csv", "TestData#csv", DataAccessMethod.Sequential), DeploymentItem("TestProject1.Tests2\\TestData.csv"), TestMethod()]
        public void SumTest() {
            Program target = new Program();
            int x = TestContext.DataRow.Field<int>("x");
            int y = TestContext.DataRow.Field<int>("y");
            int expected = TestContext.DataRow.Field<int>("answer");
            int actual;
            actual = target.Sum(x, y);
            Assert.AreEqual(expected, actual);                
        }

こっちの方がToStringもint.Parseもしなくて個人的には好きです。



================================
過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。