さとやn Blog

試合はRuby,勝負はC#!

2011年05月

Apple MagicTrackPadを使い続けて

2,3週間使い続けましたが、もうマウス要らない、という結論になりました。
腕を動かさなければならないマウスと比べて、指先だけで済んでしまうこの楽さは、慣れてしまうと、マウスの利点が思い浮かばなくなってしまいます。
操作性自体は慣れの問題もあるので、その辺は最初は戸惑ってもすぐなれると思います。
私はすぐ慣れましたが。

で、
  • スマホやタブレットで見受けられるように、マルチタッチジェスチャーは一般化するであろう。
  • ノートブックはトラックパッド、デスクトップはマウス、といった切り替えが不要。できればどっちとも同じ方が良いですよね。
  • 時期MacOS(Lion)ではマルチタッチジェスチャーを大幅に導入する模様。
ってことを考えると、やっぱりこっちかなー、という事で。
 

monoが死んだ?


http://www.infoq.com/jp/news/2011/05/Mono-II

やっとMonoTouchを使い始めたばかりなのに、Novelを買収したAttachmateとか言うドイツの企業がMonoチームを切り捨ててしまったようです。
で、リーダーの人は新しい会社を立ち上げてそちらでMonoを継続する模様。
新しい会社は、 
http://www.xamarin.com/

まだトップページしかないみたい。

もうなんだったらMicrosoftが正式にLinuxやOSX向けに.NET Framework出してくれないかなー、、、。
がんばれ、Mono!!

C#でiPhone HelloWorldやってみた

ようやく今頃になってMonoTouchを使ってC#でiPhoneアプリ作成を試してみました。
HelloWorldレベルのものですが、いやー、やっぱりC#で作れるっていいなーと思いました。
特に仕事でJavaばっかり触ってたので、ほんとちょっとした短いコードでも洗練された言語ってホント気持ちがいい、、。 

Windows Vista or 7 の64bit版で PrintDialogが機能しない

ずーっと以前(.NET Framework2.0が最新だった頃)に作ったプログラムで、印刷ができないので直してくれ、との依頼があり、調査したところ、どうも64ビット版のWindowsの場合のみに発生する現象のよう。
で、スクリーンキャプしたものを印刷する機能で、キャプチャするのにWindowsAPIを使っていたから、その辺かな? でも、.NET Framework2.0からスクリーンキャプチャするAPIが追加されてるみたいだから(今頃知った)そいつに書き換えて試してみよう、ということで、やったのですが、うんともすんとも言わない。
どうも PintDialog.Show で止まってる、というか、何も起こらない(エラーになるわけでもない)。

windows 64bit PrintDialog でぐぐったら、

PrintDialog.UseEXDialog プロパティ

 というものがあり、MSDNのドキュメントをよむと、

AMD64 プロセッサの場合、このクラスは、UseEXDialog プロパティを true に設定しないと動作しない可能性があります。
とのこと。

なんだそれ? と思いながら早速該当プロパティにTrueをセットして、実行してみたら、あっさりOK。

1時間の試行錯誤が無駄だったようです。
 
MSDNを読んでもこのプロパティだけ説明が一切ないというのが凄い。 

NUnitの結果をHTMLで表示する

.NETでもSpecFlowアドインによってSpecテストが出来ることはわかったのですが、結果をHTMLで表示できるみたいなこともガイドに書いてありました。
で、どうやるんだろう? とよく読んでみたら
  1. nunit-console でテストプロジェクトを実行してXMLファイルを生成して
  2. specflow.exe でHTML生成する
てな手順でやるようです。


こんな感じ。
※環境はMac上のmonoです。


#MySpec.dllはテストプロジェクト(nUnit)
nunit-console -labels -out=TestResult.txt -xml=TestResult.xml ./bin/Debug/MySpec.dll


mono specFlowを解凍したディレクトリ/tools/specflow.exe nunitexecutionreport ./MySpec.csproj


とやってやると、こんな感じのHTMLが生成される。
テスト3つしかないから寂しい。それにfeatures 0 ってのもよくわからない、、、。
10)



MonoDevelop (C#) で Specを使ってテストを書いてみる

最近Javaを使う仕事をしていたので、何年かぶりにxUnitを使ったテストを書いていたのですが、やっぱり仕様をテストコード上に直接表現できるSpecの方が私は好きです。
で、ちょっと調べたらVisualStudioのアドインでSpecFlowなるものがあることを発見。で、ついでにMonoDevelop版もあることを発見。肝心のJavaの方は、なんかScalaを使ったものはあるようですが、まだまだjUnitが主流のようです。まあ、Javaの世界だからこれは仕方ない。

というわけで今回はMonoDevelopを使ってC#でSpecテストを書いてみた。

MonoDevelopの Tool -> Add-in Manager からSpecFlow Supportをインストール。
27)

次にSpecFlowのサイトから、というかGitHubからdllをダウンロード。
http://specflow.org/home.aspx
※Windows版はmsiインストーラ版が用意されていますが、それ以外の場合はZIPファイルをダウンロード&解凍して使う必要があります。

足し算をするクラスのテストをSpecFlowを使って書いてみる。
まず、NunitLibraryProjectをMySpecという名前で新規作成してみる。というのもSpecFlowは内部でNUnitを使っているので、デフォルトでNunitのライブラリを参照するように設定してくれるNunitLibraryProjectがちょっと楽だから。
23)

次にライブラリの参照でダウンロード&解凍したTechTalk.SpecFlow.dllを追加。
01)

次に、ファイルの新規作成で SpecFlowFeatureを追加。ここではCalculator.featureという名前で作ってみる。
32)

サンプルとしてこんな感じのモノが書かれている。

		Feature: Addition
			In order to avoid silly mistakes
			As a math idiot
			I want to be told the sum of two numbers

		@mytag
		Scenario: Add two numbers
			Given I have entered 50 into the calculator
			And I have entered 70 into the calculator
			When I press add
			Then the result should be 120 on the screen
	
先頭のFeature: の部分はタイトルとフリーテキストが入力可能で、まあ、こんな機能のテストをしますよー的なことを書いとけばいいんだと思います。
で、Scenarioってのがそれぞれのテストケースを書くところのよう。多分意味は
  • Given : 事前の条件的なこと(〜の場合に)
  • When : テスト対象の操作的なこと(〜をしたら)
  • Then : 結果(~になるはず)
てな感じだと思います。
この場合だと、50と70を入力して、addを押したら、結果は120を表示されるはず、てなテストになります。

とりあえずこの状態でテストを実行してみると結果はこんな感じになる。
44)

		Running MySpec.MySpec.MySpec.AdditionFeature.AddTwoNumbers ...
		Given I have entered 50 into the calculator
		-> No matching step definition found for the step. Use the following code to create one:
		    [Binding]
		    public class StepDefinitions
		    {
		        [Given(@"I have entered 50 into the calculator")]
		        public void GivenIHaveEntered50IntoTheCalculator()
		        {
		            ScenarioContext.Current.Pending();
		        }
		    }

		And I have entered 70 into the calculator
		-> No matching step definition found for the step. Use the following code to create one:
		    [Binding]
		    public class StepDefinitions
		    {
		        [Given(@"I have entered 70 into the calculator")]
		        public void GivenIHaveEntered70IntoTheCalculator()
		        {
		            ScenarioContext.Current.Pending();
		        }
		    }

		When I press add
		-> No matching step definition found for the step. Use the following code to create one:
		    [Binding]
		    public class StepDefinitions
		    {
		        [When(@"I press add")]
		        public void WhenIPressAdd()
		        {
		            ScenarioContext.Current.Pending();
		        }
		    }

		Then the result should be 120 on the screen
		-> No matching step definition found for the step. Use the following code to create one:
		    [Binding]
		    public class StepDefinitions
		    {
		        [Then(@"the result should be 120 on the screen")]
		        public void ThenTheResultShouldBe120OnTheScreen()
		        {
		            ScenarioContext.Current.Pending();
		        }
		    }
	
ステップ定義とかいうものが必要になってくるらしい。というわけでステップ定義とやらを追加してみる。

ファイルの新規作成で、SpecFlow Spec Definitionを選択して適当にCalculatorStepという名前で作ってみると、サンプルコード入りのファイルが作成されるので、とりあえずサンプルのメソッドは全て削除。するとこんな感じ。 58)

		using System;

		using TechTalk.SpecFlow;

		namespace MySpec
		{
			[Binding]
			public class CalculatorStep
			{
			}
		}
	

で、ここで上記テストの実行結果にある定義すべきメソッドをコピペして貼り付ける。するとこんな感じになる。

		using System;
		using TechTalk.SpecFlow;

		namespace MySpec
		{
			[Binding]
			public class CalculatorStep
			{
				[Given(@"I have entered 50 into the calculator")]
				public void GivenIHaveEntered50IntoTheCalculator ()
				{
					ScenarioContext.Current.Pending ();
				}

				[Given(@"I have entered 70 into the calculator")]
				public void GivenIHaveEntered70IntoTheCalculator ()
				{
					ScenarioContext.Current.Pending ();
				}

				[When(@"I press add")]
				public void WhenIPressAdd ()
				{
					ScenarioContext.Current.Pending ();
				}

				[Then(@"the result should be 120 on the screen")]
				public void ThenTheResultShouldBe120OnTheScreen ()
				{
					ScenarioContext.Current.Pending ();
				}
			}
		}

	
これでテストを実行するとさっきとは違ったメッセージになる。
		Running MySpec.MySpec.MySpec.AdditionFeature.AddTwoNumbers ...
		Given I have entered 50 into the calculator
		-> pending: CalculatorStep.GivenIHaveEntered50IntoTheCalculator()
		And I have entered 70 into the calculator
		-> skipped because of previous errors
		When I press add
		-> skipped because of previous errors
		Then the result should be 120 on the screen
		-> skipped because of previous errors
	

まだ実際に動くCalculatorクラスなんてものはないけど、このシナリオ通りにテストコードを書いてみる。この場合、まだ物がないので、完全に呼び出す側の立場でメソッド名とかを考えられる、、、。

		using System;
		using NUnit.Framework;
		using TechTalk.SpecFlow;

		namespace MySpec
		{
			[Binding]
			public class CalculatorStep
			{

				Calculator target = new Calculator();

				[Given(@"I have entered 50 into the calculator")]
				public void GivenIHaveEntered50IntoTheCalculator ()
				{
					target.Enter (50);
				}

				[Given(@"I have entered 70 into the calculator")]
				public void GivenIHaveEntered70IntoTheCalculator ()
				{
					target.Enter (70);
				}

				[When(@"I press add")]
				public void WhenIPressAdd ()
				{
					target.PressAdd ();
				}

				[Then(@"the result should be 120 on the screen")]
				public void ThenTheResultShouldBe120OnTheScreen ()
				{
					Assert.AreEqual (120, target.Result);
				}
			}
		}
	
この段階では当たり前だけどテストはおろか、コンパイルも通らない。

じゃあ、実際に動くクラス Calculatorを作る。
Add New Projectで、新規プロジェクトを追加。名前は適当にCalcとしてみる。
01)

で、このプロジェクトにCalculatorクラスを追加。
59)

で、必要なメソッドを、プロパティ等のスケルトンを実装すると、こんな感じ。

		using System;
		namespace Calc
		{
			public class Calculator
			{
				public int Result { get; set; }

				public Calculator ()
				{
				}

				public void Enter (int number)
				{
				}

				public void PressAdd ()
				{ 
				}
			}
		}
	

次に、テストプロジェクトの方で、このクラスを参照できるようにライブラリ参照の設定でプロジェクト参照を設定&using句も追加。
07)
18)

		using System;
		using NUnit.Framework;
		using TechTalk.SpecFlow;
		using Calc;
	
これでテストを実行してみると、結果はちゃんと失敗する。
39)

で、今度はテストがちゃんと通るようにCalculatorクラスのメソッドの中身を実装する。とりあえずこんな感じで実装てみる。

		using System;
		using System.Collections.Generic;

		namespace Calc
		{
			public class Calculator
			{

				List _numbers = new List(2);
				public int Result { get; set; }

				public Calculator ()
				{
				}

				public void Enter (int number)
				{
					_numbers.Add (number);
				}

				public void PressAdd ()
				{ 
					_numbers.ForEach( number => this.Result += number);			
				}
			}
		}
	
これで、再度テストを実行してみる。
48)
ちゃんとグリーンで成功!

でもこの感じだと、Enter(50), Enter(70)とかそれぞれにステップ定義の方にメソッドがあって、じゃあ、80を入力した場合のテストを書く場合は、こんな感じで都度メソッドを追加していくのか?、という疑問が、、、。

		//いちいちパラメータ毎にメソッドが必要?
		[Given(@"I have entered 80 into the calculator")]
		public void GivenIHaveEntered80IntoTheCalculator ()
		{
			target.Enter (80);
		}
	
実はその辺もちゃんと用意されていて、正規表現を使ってパラメータ化できたりします。で、featureとステップ定義をこんな感じで書き換えてみる。
feature:
		Feature: Addition
			In order to avoid silly mistakes
			As a math idiot
			I want to be told the sum of two numbers

		@mytag
		Scenario: Add two numbers
			Given I have entered "50" into the calculator
			And I have entered "70" into the calculator
			When I press add
			Then the result should be "120" on the screen
	
ステップ定義:
		using System;
		using NUnit.Framework;
		using TechTalk.SpecFlow;
		using Calc;

		namespace MySpec
		{
			[Binding]
			public class CalculatorStep
			{

				Calculator target = new Calculator();

				//[Given(@"I have entered 50 into the calculator")]
				[Given(@"I have entered ""(\d+)"" into the calculator")]
				public void GivenIHaveEnteredNumberIntoTheCalculator (int number)
				{
					target.Enter (number);
				}

		//		[Given(@"I have entered 70 into the calculator")]
		//		public void GivenIHaveEntered70IntoTheCalculator ()
		//		{
		//			target.Enter (70);
		//		}

				[When(@"I press add")]
				public void WhenIPressAdd ()
				{
					target.PressAdd ();
				}

				//[Then(@"the result should be 120 on the screen")]
				[Then(@"the result should be ""(\d+)"" on the screen")]
				public void ThenTheResultShouldBeOnTheScreen (int result)
				{
					Assert.AreEqual (result, target.Result);
				}
			}
		}
	
featureの方はパラメータ化したい値をダブルクオーテーションで囲みます。
ステップ定義の方は各メソッドのAttributeの中でパラメータ化した部分を正規表現パターンで置き換えます。ここではintが渡されるので数値以外受け付けないようにしてある。

やってみた感じ、やっぱりxUnitよりはSpecの方がいいですね。
また、結果をHTMLで表示したり、ということもできたりするようです。詳しくは下記のサイトとかガイドをご参照ください。
http://specflow.org/home.aspx
http://github.com/downloads/techtalk/SpecFlow/SpecFlow%20Guide.pdf

Apple マジック・トラックパッドを買う

ここにきて急にマジック・トラックパッドが欲しくなったので、購入してしまいました。
正直MacBookAirで使っているとエリアが狭いせいかあまり使いやすいとは思わなかったけど、こっちは見ての通りかなりの面積があって非常に使いやすいです。

懸念していたテキストの選択や、表計算ソフトのセルのサイズ調整などの操作も全く問題なくできて、拍子抜けでした。MacBookAirでやり辛いと感じたのはやっぱり狭いからなのか?

まだグラフィック系のソフトは試してないので何とも言えませんが、想像以上に快適で(過度な期待はしていなかったからか)1〜2時間ほど使用して、マウス(マジック・マウス)は電源をオフってしまいました(そっちは職場で使おうかな、、、)。

以前マウスからトラックボールに変更しようとして2ヶ月くらい試したけど、どうしても馴染めなかったのに、こっちは良いかも知れない、、、。
ていうか個人的にはマジック・マウスより良いです。


IMG_0478




livedoor プロフィール
QRコード
QRコード
  • ライブドアブログ