始めよう!Silverlight

第8回 Silverlightで単体テスト(後編)

この記事を読むのに必要な時間:およそ 3.5 分

では,テストプロジェクトから追加したSimulateButtonClickメソッドを呼び出して,ボタンクリック時の動作をテストするコードを追加します。PageTestクラスに以下のメソッドを追加します。

[TestMethod]
public void ボタンクリックでラベルにHelloworldが表示されるべき()
{
  //①
  Assert.IsNull(page.messageTextBlock.Text);
  //②
  page.SimulateButtonClick();
  //③
  Assert.AreEqual("Hello world", page.messageTextBlock.Text);
}

①の部分でまずはデフォルトのなにも設定されていない状態を検証しています。その場合は値はnullになります。

②の部分でボタンがクリックされたことをシミュレートしています。ですのでSilverlightプロジェクトの中ではボタンがクリックされた場合と,同様の処理が行われていることになります。

最後の③の部分で,ボタンクリック後のラベルに「Hello world」が表示されているかどうかを検証しています。

それでは実行してみます。実行画面をじっくり見ていただくと一瞬ですがPageに追加したボタンとテキストブロックが実際に表示されていることも確認できます。

画像

簡単にまとめるとUIのテストは以下のような流れで作成することになります。

  1. キーボードやマウスの操作が行われた時の処理を記述
  2. Internalで上記の操作を呼ぶシミュレート用のメソッドを記述
  3. テストクラスより上記のシミュレート用のメソッドを呼ぶテストメソッドを記述

非同期のテスト

前編・後編と続けましたSilverlightの単体テストの最後のトピックとして非同期のテストの実行をご紹介します。Silverightではネットワークアクセスやアニメーションの実行はすべて非同期での処理になりますので,非同期をテストできることは非常に重要になります。

まずは非同期検証用に以下のメソッドをPageTestクラスに追加します。

[TestMethod]
[Asynchronous]  //①
public void 非同期処理のテスト()
{
}

非同期のテストには①のAsynchronous属性を設定します。この属性が設定されていないとテストは正常に実行されません。

非同期処理自体については今回はテストメソッドの中にBackgroundWorkerを使って実装します。以下のコードを先ほど追加した[非同期処理のテスト]メソッドの中に追加します。

var worker = new BackgroundWorker();
var result = false; //①
var finishedWork = false; //②
worker.DoWork += (s, e) => //③
{
  e.Result = true;
};
worker.RunWorkerCompleted += (s, e) => //④
{
  result = (bool)e.Result;
  finishedWork = true;
};

まず,①のresult変数ですが,これは検証するための変数です。この変数の値がtrueになっていればテスト成功,falseであればテスト失敗と判定します。②のfinishedWork変数は非同期処理が終了したかどうかを判定するための変数です。

③のBackgroundWorkerのDoWorkに設定された匿名デリゲートはBackgrondWorkerが実行された時に呼び出されます。この中で処理結果に true を設定しています。最後にこの処理結果をテストで判定します。

④のBackgroundWorkerのRunWorkerCompletedに設定された匿名デリゲートはBackgrondWorkerの処理が完了した時に実行されます。ここでは処理の結果をテストで検証するresult変数に代入し,finishedWork変数にtrueを代入することで,処理が終わったことを設定しています。

では,最後に検証のコードを追加します。次のコードを上記のコードの下に追加します。

this.EnqueueCallback(() => worker.RunWorkerAsync()); //①
this.EnqueueConditional(() => finishedWork); //②
this.EnqueueCallback(() => Assert.IsTrue(result)); //③
this.EnqueueTestComplete(); //④

これらのSilverlightTestクラスがもっている, EnqueueXXXXメソッドが非同期処理のテスト用のヘルパーメソッドになります。それぞれに設定されたデリゲートはテストメソッドの実行が終了した後に,設定された順番で呼び出されます。

まず①でEnqueueCallbackにBackgroundWorkerの処理を実行するデリゲートを設定しています。ここで非同期処理を実行します。テストメソッドの実行が終了した後に,最初にこのデリゲートが呼び出されます。

次に②でEnqueueConditionalメソッドにfinishedWork変数の値が戻り値になるデリゲートを設定しています。EnqueueConditionalメソッドは戻り値の値がtrueになるまで繰り返し,設定されているデリゲートを呼び出すことで,非同期処理が終了するまでの待機を行います。

③ではEnqueueCallbackにアサートを実行するデリゲートを設定しています。ここでresult変数の値がtrueであればテストが成功になります。

最後に④でテストが終了したことを設定しています。

ではテストを実行してみてください。正常に実行されるとおもいます。非同期処理のテストはデバックなしで実行を行ってください。デバックが有効になっている場合,例外が発生した時にVisualStudioが例外をキャッチして処理を止めてしまうためです。

画像

非同期のテストはいったんデリゲートという形で処理をキューに貯めてから実行されます。大きな流れとしては以下の順番で処理をキューに設定することになります。

  1. EnqueueCallbackで非同期処理の開始
  2. EnqueueConditionalで非同期処理の終了を待機
  3. EnqueueCallbackで非同期処理の結果を検討
  4. EnqueueTestCompleteで終了

次回予告

後編の今回は前編に引き続き,残りのUIのテストと非同期のテストをご紹介しまし。今後は様々なテストフレームワークが登場することでしょう。また,ビルドや継続的インテグレーションとの統合なども実現されていくと予想されます。

次回は,SilverlightのコントロールであるDataGridを取り上げたいと思います。お楽しみに。

著者プロフィール

丸山和秀(まるやまかずひで)

株式会社アークウェイ システムクリエイター。趣味はドラム。社会人になりたてのころは職業はドラマーだと豪語していたが,いつのまにかシステム開発の楽しさにのめりこみ,仕事内容が職業になっていた。パッケージベンダにて金融向けパッケージソフトの開発を行うSEを経て現職へ。現在は研究開発としてRIAに取り組み中。