ドローイング空間

3D-CADを中心に、雑多なことをかいています。

C#のテスト・プロジェクトを使用したHello World!

広告

テストプロジェクトの目的は、対象とするプロジェクトが仕様通りに正しく動作することを保証することです。 テストするコードを記述する前に、 テストするコードを記述する開発スタイル「テスト駆動開発 (TDD: test-driven development)」を選択する場合は、 テストプロジェクトから作業を開始します。

 

C#は、柔軟性を持つ開発環境です。そのため、実験的な試みや最新の技術が、当たり前のように導入されます。 C#の高技能者は、この環境を有効に使えるのでしょうが、 C#をこれから習得する人には、情報をどう探して、習得して行くのに、 どうしたらいいのか、さっぱりわからないというのが現実だと思います。

本来、C#は、WindowsGUIアプリケーションを開発するための一番簡単なアプリケーション開発環境のはずなのですが、 新たに学ぼうとした時の、一体ここはどこなのだろうと途方にくれる「魔窟」感は、半端ありません。

チュートリアルや、サンプル・アプリケーションと呼ばれるものを写経していく方法で学んで行くことがが正しい方向と理解していても感じる「徒労感」、 これは何なのでしょう。「徒労感」ではなく、「達成感」を感じる段階に、早く進みたいものです。

テストプロジェクトを使用して、コンソール・アプリケーションのHello Worldを作成します。

Visual Studio Community 2015を使用しました。

コンソール・アプリケーション・プロジェクトを作成します。

Visual Studioで、「ファイル」→「新規作成」→「プロジェクト」を選択します。 キーボードショートカットを使う場合は、Control + Shift + Nを入力します。

Visual Studioで、「ファイル」→「新規作成」→「プロジェクト」を選択します。

新しいプロジェクトダイアログで、テンプレートから、「Windows」、「コンソールアプリケーション」を選択します。 場所は、新たにTestProjectsフォルダを作成し、プロジェクトの名前として、HelloWorldに設定します。

新しいプロジェクトダイアログで、テンプレートから、「Windows」、「コンソールアプリケーション」を選択します。

ダイアログの下部のフィールド

  • 名前フィールド
    • ディスク上の.csprojファイルの名前を決定します。
    • コンパイルされた出力のファイル名を決定する。(この名前は、後から変更できます)
    • 新規作成れたコードのデフォルトの名前空間を設定します。
  • 場所フィールド

    関連するソリューションの作成方法を決定するためのチェクボックス「ソリューションのディレクトリを作成」が提供されています。

    「ソリューションのディレクトリを作成」チェックボックス

    • 選択しない場合

      プロジェクトは、ソリューションと同じ名前になり、ディスク上の同じフォルダに格納されます。

    • 選択する場合(既定)

      ソリューションフォルダの下に、プロジェクトフォルダが作成されます。

      ※1つのソリューションに、複数のプロジェクトが存在する場合は、こちらを選択する。

  • ソリューション名フィールド

    プロジェクト名とソリューション名を別の名前に変更する際に使用します。自動で、プロジェクト名と同じ名前が記入されます。

ソリューションエクスプローラーを確認すると、Hello Worldプロジェクトが作成されているのが分かります。

ソリューションエクスプローラーを確認すると、Hello Worldプロジェクトが作成されているのが分かります。

単体テスト・プロジェクトをソリューションに追加します。

ソリューションエクスプローラーの一番上のノードで右クリックし、「追加」→「新しいプロジェクト」を選択します。

※もう1つの方法は、再び、新しいプロジェクトダイアログを開くことです。既に新しいプロジェクトを開いている場合は、 更に、ドロップダウンリストが表示されるので、「ソリューションに追加」か、「新しいインスタンスに作成」のどちらかを選択します。

ソリューションエクスプローラーの一番上のノードで右クリックし、「追加」→「新しいプロジェクト」を選択します。

「Visual C#」→「テスト」を選択し、「単体テストプロジェクト」を選択します。名前は、「HelloWorld.Test」を指定します。 特に命名規則は存在しないので、他の名前でも構いません。入力が完了したらOKをクリックします。

「Visual C#」→「テスト」を選択し、「単体テストプロジェクト」を選択します。名前は、「HelloWorld.Test」を指定します。

ソリューションに、テストプロジェクトが追加されます。

ソリューションに、テストプロジェクトが追加されます。

テストプロジェクトの目的は、対象とするプロジェクトが仕様通りに正しく動作することを保証することです。 テストするコードを記述する前に、テストするコードを記述する開発スタイル「テスト駆動開発 (TDD: test-driven development)」を選択する場合は、テストプロジェクトから作業を開始します。

この作業を開始するためには、このテストプロジェクトは、 HelloWorldプロジェクトの中にアクセスする必要があります。 そのためには、参照を設定する必要があります。

参照を追加する

ソリューションエクスプローラーで、HelloWorld.Testプロジェクトの参照ノードの上で右クリックして、「参照の追加」を選択します。

ソリューションエクスプローラーで、HelloWorld.Testプロジェクトの参照ノードの上で右クリックして、「参照の追加」を選択します。

参照マネージャーダイアログが表示されるので、「プロジェクト」を選択し、 「HelloWorld」のチェックボックスにチェックを入れ、OKをクリックします。

参照マネージャーダイアログが表示されるので、「プロジェクト」を選択し、 「HelloWorld」のチェックボックスにチェックを入れ、OKをクリックします。

参照が追加されます。

参照が追加されます。

単体テストの記述

UnitTest1.csの名前をWhenProgramRan.csに変更します。

UnitTest1.csで右クリックして、「名前の変更」を選択します。

UnitTest1.csで右クリックして、「名前の変更」を選択します。

名前をWhenProgramRan.csに変更します。

名前をWhenProgramRan.csに変更します。

「はい」を選択します。

「はい」を選択します。

単体テストをどのように記述するべきかについては、さまざまな流儀があります。

  • テストしたいクラスごとに1つのテストクラスを作る
  • 特定のクラスをテストしたいシナリオごとに、クラスを1つ作る

この例では、後者の方法を採用し、目的とするシナリオで、 コードが正しく動作するか確認する項目ごとに、1つのメソッドを作成します。

作成するプログラムは、プロクラム名から、 推測できるように、プログラムを実行すると、「Hello, world!」というメッセージを表示します。

これをテストするためには、実行時に、プリおグラムが要求されたメッセージが出力されるか確認します。

WhenProgramRan.csのコードを以下の様に変更します。

変更前


using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace HelloWorld.Test
{
    [TestClass]
    public class WhenProgramRan
    {
        [TestMethod]
        public void TestMethod1()
        {
        }
    }
}

変更後


using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace HelloWorld.Test
{
    [TestClass]
    public class WhenProgramRan
    {
        private string _consoleOutput;

        [TestInitialize]
        public void Initialize()
        {
            var w = new System.IO.StringWriter();
            Console.SetOut(w);

            Program.Main(new string[0]);

            _consoleOutput = w.GetStringBuilder().ToString().Trim();
        }

        // テスト
        [TestMethod]
        public void SayHelloWorld()
        {
            Assert.AreEqual("Hello, World", _consoleOutput);
        }
    }
}

テストは、最後の部分にあります。

このテストは、プログラムの出力が、「Hello, World!」というメッセージでなければいけないことを示しています。 そうでなければ、失敗したことを報告します。

ここでは、プログラムが、コンソールに、ある特定のメッセージを出力しているかどうかを検証します。 実際のアプリケーションでは、おそらく、出力を多少抽象化するように工夫して、 単体テスト用に、テスト目的に抽象化した代替版を使うことになります。

この例では、プログラムを複雑化させることを避けるため、 プログラムの出力が想定通りか確認するために、コンソール出力を傍受するテストを作成しています。

通常は、定義の通り、単体テストは、プログラムの独立した小さな部分をテストします。

今回のプログラムは、非常に簡単なので、たった1つの機能しかなく、プログラムの実行時にその機能を実行します。 つまり、このテストでは、プログラムのエントリポイントを起動する必要があります。

そこで、プログラムのエントリポイントを直接実行しています。C#アプリケーションでは、 プログラムのエントリポイントは、通常、Programと呼ぶクラスの中で定義されているMainと呼ぶメソッドです。

残念ながら、この方法には、問題があります。プログラムのエントリポイントは、 通常は、ランタイムからしかアクセスできません。 通常は、他から事項する必要はありませんが、この例では、コードを動かす唯一の方法です。

このコードをコンパイルするには、Mainプログラムに変更を与える必要があります。

HelloWorldプロジェクトのProgram.csファイルを開きます。

HelloWorldプロジェクトのProgram.csファイルを開きます。

テストが、コードにアクセスできるように、2行の先頭に、publicキーワードを追加します。

※テストスイートのアクセスを許可するために、 プログラムに、InternalsVisibleToAttributeを適用する方法でも、同じ効果があります。

テストが、コードにアクセスできるように、2行の先頭に、publicキーワードを追加します。

これで、単体テストを実行する準備ができました。単体テストを実行するためには、単体テストを実行するために、 「テスト」→「ウインドウ」→「テスト エクスプローラー」メニュー項目から、単体テストエクスプローラーを開きます。

単体テストを実行するためには、単体テストを実行するために、 「テスト」→「ウインドウ」→「テスト エクスプローラー」メニュー項目から、単体テストエクスプローラーを開きます。

テストエクスプローラーが表示されました。

テストエクスプローラーが表示されました。

「ビルド」→「ソリューションのビルド」を選択し、ソリューションをビルドします。

「ビルド」→「ソリューションのビルド」を選択し、ソリューションをビルドします。

テストエクスプローラーに、SayHelloWorldの項目が現れます。 「すべてを実行」を選択すると、テストが開始されます。

「すべてを実行」を選択すると、テストが開始されます。

メインプログラムには、まだ、コードを何も記述していないので失敗します。

メインプログラムには、まだ、コードを何も記述していないので失敗します。

Hello Worldコードの追加

HelloWorldプロジェクトのProgram.csファイルを開きます。 Mainメソッドの中に、Console.WriteLine("Hello, World!");を追加します。

Mainメソッドの中に、Console.WriteLine("Hello, World!");を追加します。

HelloWorldプロジェクトのProgram.csファイルを開きます。 Mainメソッドの中に、Console.WriteLine("Hello, World!");を追加します。

HelloWorldプロジェクトのProgram.csファイルを開きます。Mainメソッドの中に、Console.WriteLine("Hello, World!");を追加します。

現在、Program.csファイルの内容は、以下のようになっています。


using System;

namespace HelloWorld
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");
        }
    }
}

テストを実行する

プログラムが完成したので、テストを実行します。

テストエクスプローラーで、「すべて実行」をクリックします。

テストエクスプローラーで、「すべて実行」をクリックします。

失敗しました。テストで確認する文字列に「!」を記入し忘れていたようです。

失敗しました。

HelloWorld.TestプロジェクトのWhenProgramRan.csを開いて、修正します。


        // テスト
        [TestMethod]
        public void SayHelloWorld()
        {
            Assert.AreEqual("Hello, World!", _consoleOutput);
        }

再度テストを実行します。

テストに成功しました。

テストに成功しました。

このまま実行すると、「Hello, World!」と文字列がコンソールに表示されても、 コンソールがすぐに閉じてしまい確認できないので、Program.csファイルに、「Console.ReadLine();」を追加します。

Program.csファイルは、以下のようになります。


using System;

namespace HelloWorld
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");

            // キーの入力を求める
            Console.ReadLine();
        }
    }
}

ツールバーで、開始アイコンをクリックします。

ツールバーで、開始アイコンをクリックします。

Hello, World!と表示されます。なにかキーを押すと、コンソールウインドウが閉じます。

Hello, World!と表示されます。なにかキーを押すと、コンソールウインドウが閉じます。

参考:

プログラミングC# 第7版 p11-22

プログラミングC# 第7版