巨人の肩の上に登る

先人の積み重ねた発見に基づいて、なにかを発見しようとすることを指す。

Mac OSX(mono)でC#のユニットテストをする

f:id:mayo_yamasaki:20140908152016g:plain

C#ユニットテスト単体テスト)を書いてみた。
NUnitというフレームワークデファクトっぽいので、これのCUIでの使い方をメモ。

install

以前に書いた記事 monoとXamarin StudioでC# でXamarin Studioを入れていたので、恐らく、NUnit関連で必要なものは入っていると思います。
一応、$ which nunit-consolenunit-consoleのパスが通ってるか確認。

Sample

準備が整ったので、早速試してみましょう。
HelloTest.csを下記の内容で作成。

using NUnit.Framework;
using System;

namespace HelloTest
{
    [TestFixture]
    public class NUnitTestClass
    {
        [Test]
        public void TestCase1 ()
        {
            Assert.AreEqual (2, 1 + 1);

        }

        [Test]
        public void TestCase2 ()
        {
            Assert.AreEqual (2, 2 - 1);
        }
    }
}

分かり易く、失敗するケースで試してみます。
TestCase2の方は明らかに誤りなので、コケるはずです。
NUnit.Frameworkの詳細に関しては、公式のドキュメントを参照されたい。

Test

手順としては、テストコードをライブラリ形式にコンパイルしてから、nunit-consoleで実行します。

コンパイル
$ mcs HelloTest.cs -reference:nunit.framework.dll -target:library
実行
$ nunit-console HelloTest.dll
結果
NUnit version 2.4.8
Copyright (C) 2002-2007 Charlie Poole.
Copyright (C) 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov.
Copyright (C) 2000-2002 Philip Craig.
All Rights Reserved.

Runtime Environment -
   OS Version: Unix 13.3.0.0
  CLR Version: 2.0.50727.1433 ( 3.8.0 ((no/45d0ba1 Tue Aug 26 20:33:43 EDT 2014) )

..F
Tests run: 2, Failures: 1, Not run: 0, Time: 0.107 seconds

Test Case Failures:
1) HelloTest.NUnitTestClass.TestCase2 :   Expected: 2
  But was:  1

...

上記の出力結果から、問題の箇所でコケていることがわかります。
ちなみに、テスト結果はxmlで保存されます。


関連記事

monoとXamarin StudioでC#

C# を使ってみたかったので,Xamarinで試してみる.

Xamarin とは

Xamarinは,.NETと互換性のある iOS, Android, Mac, WindowsアプリをC#で書くことが可能な,クロスプラットフォーム開発環境です..NETとの互換は有償ではあるもの、小さいサイズのアプリケーションの開発環境は無償で提供されています。(料金表

付属する,Xamarin Studioは名前から類推できますが, IDEです.Windows, Mac版が存在しています.

monoとは

monoは,Mac環境におけるC#コンパイラーです.OSSC#コンパイラで良さげなものはあるのだろうか...

余談1

Xamarinの経緯.Xamarin - wikipediaより.

2000年6月、マイクロソフト.NET Frameworkをはじめて公表した。Ximianのミゲル・デ・イカザはこのLinux版が実現可能か調査を開始した。その後、2001年6月19日、Monoというオープンソースプロジェクトが立ち上げられた。MonoをサポートしていたXimianは2003年8月4日、ノベルにより買収された。
2011年4月のAttachmate(英語版)によるノベルの買収ののち、Attachmateは数百名にも上るノベル従業員のレイオフを発表した。この中にはMonoの開発者が含まれていた。
同年5月16日、ミゲルは彼のブログにて、Monoを新しい企業Xamarinで開発ならびにサポートすると発表した。

余談2

C# より C Sharp の方が,個人的には字面が良い.
また,googleしてるとC Sharpの表記が多い気もします.

C Sharpを書いてみる

今回は C Sharp を書いてみるのが目的です(ので,Xamarinである必要もないのですが...).

Xmarin Studioを起動してみるとこんな感じです.

f:id:mayo_yamasaki:20131216033658p:plain

New... より新しいプロジェクトを作ります.

f:id:mayo_yamasaki:20131216033934p:plain

C# > コンソールプロジェクト より新しいプロジェクトを作成します. IDEは割とすっきりした印象 .

f:id:mayo_yamasaki:20131216034246p:plain

今回は,シンプルにフィボナッチ数を求めるアルゴリズムを実装してみる.

再帰

とりあえず再帰な実装.O(2n).

public static int fibonacciRecur (int n)
{
    return (n < 2) ? n : fibonacciRecur (n - 1) + fibonacciRecur (n - 2);
}

動的計画法

わかりにくいが動的計画法.O(n).

public static int fibonacciDp (int n)
 {
    int a = 0, b = 1;
    int tmp = 1;

    for (int i = 1; i < n; i++)
    {
        tmp = a + b;
        a = b;
        b = tmp;
    }

    return (n==0) ? 0 : tmp;
}

一般式

いわゆるビネの公式で求められる.O(1).

public static int fibonacciGe (int n)
{
    return  (int)Math.Round((
                Math.Pow ((1.0 + Math.Sqrt (5.0)) / 2.0, (double)n)
                - Math.Pow ((1.0 - Math.Sqrt (5.0)) / 2.0, (double)n)
            ) / Math.Sqrt (5.0));
}

完全なコード

using System;

namespace Fibonacci
{
    class MainClass
    {
        public static void Main (string[] args)
        {
            
            if (args.Length != 1)
            {
                Console.WriteLine ("Error : Required one integer arg.");
                return;
            }

            int n;

            try
            {
                n = Convert.ToInt32 (args[0]);
                if (n < 0) { throw new Exception( "Error : Required positive integer." ); };
            }
            catch (InvalidCastException e)
            {
                throw e;
            }

            Console.WriteLine (fibonacciRecur (n)); // Recursive approach
            Console.WriteLine (fibonacciDp (n));    // Dynamic programming approach
            Console.WriteLine (fibonacciGe (n));    // General expression approach

        }

        public static int fibonacciRecur (int n)
        {
            return (n < 2) ? n : fibonacciRecur (n - 1) + fibonacciRecur (n - 2);
        }

        public static int fibonacciDp (int n)
        {
            int a = 0, b = 1;
            int tmp = 1;

            for (int i = 1; i < n; i++)
            {
                tmp = a + b;
                a = b;
                b = tmp;
            }

            return (n==0) ? 0 : tmp;
        }

        public static int fibonacciGe (int n)
        {
            return  (int)Math.Round((
                        Math.Pow ((1.0 + Math.Sqrt (5.0)) / 2.0, (double)n)
                        - Math.Pow ((1.0 - Math.Sqrt (5.0)) / 2.0, (double)n)
                    ) / Math.Sqrt (5.0));
        }
    }

}

実行

実行方法は,コンソールプロジェクトなので,exeファイルを直接実行する.

# build target によるので,下記のいづれかにexeがあります
PROJECT_ROOT/PROJECT_NAME/bin/Debug
PROJECT_ROOT/PROJECT_NAME/bin/Release
$ mono Fibonacci.exe 12
144  // Recursive approach
144  // Dynamic programming approach
144  // General expression approach

余談3

新しい言語を学ぶ際に効率的な,Learn X in Y minutes をやろうとしたのですが,接続できず.
仕方ないので,最速マスターシリーズを読んでみた.

おわりに

少しだけ C Sharp を書いてみましたが,この程度ではC Sharpっぽさは分からず.


関連記事