Silverlightのツールキットユニットテスト
導入
ユニットテストは非常に高品質のソフトウェア開発のための重要です。 SilverlightをToolkitは、 。として良いサンプルが豊富なユニットテストを、同様にSilverlightをToolkitのユニットテストプロジェクト(Controls.Testing、Controls.Test.DataVisualization、Controls.Testing.Theming)を使用するSilverlightのユニットテストフレームワーク(Microsoft.Silverlight.Testing.dll &Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight.dll)が発明ジェフウィルコックス 、ユニットテストのクラスライブラリ(Controls.Testing.Common.dll)Glazaテッド発明した。 あなたについての情報役に立ちましたを見つける多くのことができるSilverlightの単体テストフレームワークのからMSDN Codeギャラリーサイトとジェフさんのブログ 。 ライブラリリリースのクラスのこのポストは主に話しテッドテストユニットのSilverlight ツールキット、フレームワークが示すと例どのように我々の上に構築されてユニットテストは。
以下は、Controls.Testing.Commonプロジェクトで、私たちのユニットテストの全体的なデザインパターンの一部のクラスを示す簡略化クラス図は、:
図1:Controls.Testing.Commonクラス図
パラレルクラス階層
それはかなりクラス上の図から明らかに、パラレルクラス階層は、です:
- FrameworkElementは< - コントロール< - はContentControl
- FrameworkElementTest < - ControlTest < - ContentControlTest
- IOverriddenFrameworkElement < - IOverriddenControlの< - IOverriddenContentControl
最初の階層は、コントロールのクラス単位されての継承チェーンですテスト。
2番目の階層は、対応するユニットテストクラスの継承チェーン、コントロールクラスは、テストされて並列接続されます。 このデザインの理由ははContentControlは、コントロールされた場合、次にContentControlTestはすべてのものControlTestをテストする必要です。 がテストクラスの設計にいくつかの一般的なパターンがあります。 YYYはからXXXの継承と仮定すると:
- YYYTestからXXXTestを継承します。 XXXTestは抽象的ではない場合は、[Testclassの]属性でマークされます。
[は] Testclassの 公共部分クラス ExpanderTest:HeaderedContentControlTest (
- XXXTestは3つの新しいプロパティを:DefaultXXXToTestは、XXXsToTest、OverriddenXXXsToTest、および3つのプロパティ(DefaultYYYToTest、YYYsToTest、OverriddenYYYsToTest)は、基本クラスYYYTestによって導入されたのオーバーライドを実装するためにそれらを使用する紹介:
#地域 HeaderedContentControlsをテストする / / / <summary> / / /、テストHeaderedContentControl(またはインスタンス派生型)を取得しますデフォルト。 / / / </概要> 公共オーバーライド HeaderedContentControl DefaultHeaderedContentControlToTest ( 得る ( DefaultExpanderToTestを返します 。 ) ) / / / <summary> / / /テストするために)型を取得インスタンスをのHeaderedContentControl(派生または。 / / / </概要> 公共オーバーライド IEnumerableを<HeaderedContentControl> HeaderedContentControlsToTest ( 得る ( 戻り ExpandersToTest.OfType <HeaderedContentControl>(); ) ) / / / <summary> / / /テストするために)型を取得インスタンスをのIOverriddenContentControl(派生または。 / / / </概要> 公共オーバーライド IEnumerableを<IOverriddenHeaderedContentControl> OverriddenHeaderedContentControlsToTest ( 得る ( 戻り OverriddenExpandersToTest.OfType <IOverriddenHeaderedContentControl>(); ) ) を#endregion HeaderedContentControlsをテストする #地域エキスパンダーをテストする / / / <summary> / / /、テストエキスパンダー(またはインスタンス派生型)を取得しますデフォルト。 / / / </概要> パブリック仮想パンダDefaultExpanderToTest ( 得る ( 戻り新しいExpander(); ) ) / / / <summary> / / /テストするために)型を取得インスタンスをのパンダ(派生または。 / / / </概要> パブリック仮想 IEnumerableを<Expander> ExpandersToTest ( 得る ( 収量戻り DefaultExpanderToTest; i = 0; i < 4; i++) 0 = するfor(int私は、私は<4;私+ +) ( パンダパンダ= 新しいExpander ( ExpandDirection =(ExpandDirection)私は、 isExpandedとして=(一%2 == 0) ); 収量戻りエキスパンダー。 ) ) ) / / / <summary> / / /テストするために)型を取得インスタンスをのIOverriddenContentControl(派生または。 / / / </概要> パブリック仮想 IEnumerableを<IOverriddenExpander> OverriddenExpandersToTest ( 得る ( 収量を破る 。 ) ) を#endregionエキスパンダーをテストする
- XXXTestは、オーバーライドGetDependencyPropertyTest方法パブリックコンストラクタがあります:
/ / / <summary> / / /テストを入手して依存関係プロパティ。 / / / </概要> / / /は、>。</リターンを依存関係プロパティのテストを<returns> 公共オーバーライド IEnumerableを<DependencyPropertyTestMethod> GetDependencyPropertyTests() ( IListを<DependencyPropertyTestMethod>テスト= TagInherited( 基本 。GetDependencyPropertyTests());
- XXXTestはTemplatePartsAreDefinedオーバーライド可能性がありますメソッドをTemplateVisualStateAreDefined、XXXは、新しいコントロールの契約を定義し、ある場合、またはその祖先の契約契約を変更:
#領域コントロール契約 / / / <summary> / / /はTemplatePartsを検証コントロールの。 / / / </概要> [は]をテストメソッド 【説明は("TemplatePartsを確認コントロールの。")] ) 公共 (TemplatePartsAreDefined オーバーライドは無効 ( IDictionaryの< 文字列を入力> templateParts = DefaultControlToTest.GetType()。GetTemplateParts(); Assert.AreEqual(1、templateParts.Count); ]); Assert.AreSameは(typeof演算 (ToggleButtonを)、[templateParts"ExpanderButton"]); ) / / / <summary> / / /ことを確認コントロールの状態をテンプレートのビジュアル。 / / / </概要> [は]をテストメソッド 【説明は("確認コントロールの状態をテンプレートのビジュアル。")]を ) 公共 (TemplateVisualStatesAreDefined オーバーライドは無効 ( > visualStates = DefaultControlToTest.GetType().GetVisualStates(); IDictionaryの< 文字列 、 文字列 > visualStates = DefaultControlToTest.GetType()。GetVisualStates(); Assert.AreEqual(12、visualStates.Count); , visualStates[ "Normal" ]); Assert.AreEqual < 文字列 >は、("CommonStatesは"では、[visualStates"ノーマル"]); , visualStates[ "MouseOver" ]); Assert.AreEqual < 文字列 >は、("CommonStatesは"では、[visualStates"マウスオーバー"]); , visualStates[ "Pressed" ]); Assert.AreEqual < 文字列 >("CommonStatesは"では、[visualStates"プレス"]); , visualStates[ "Disabled" ]); Assert.AreEqual < 文字列 >は、("CommonStatesは"では、[visualStates"無効"]); , visualStates[ "Focused" ]); Assert.AreEqual < 文字列 >は、("FocusStatesは"では、[visualStates"フォーカス"]); , visualStates[ "Unfocused" ]); Assert.AreEqual < 文字列 >は、("FocusStatesは"では、[visualStates"やり場のない"]); , visualStates[ "Expanded" ]); Assert.AreEqual < 文字列 >("ExpansionStatesは"では、[visualStates"拡張"]); , visualStates[ "Collapsed" ]); Assert.AreEqual < 文字列 >("ExpansionStatesは"では、[visualStates"倒壊"]); , visualStates[ "ExpandDown" ]); Assert.AreEqual < 文字列 >は、("ExpandDirectionStatesは"では、[visualStates"ExpandDown"]); , visualStates[ "ExpandUp" ]); Assert.AreEqual < 文字列 >は、("ExpandDirectionStatesは"では、[visualStates"ExpandUp"]); , visualStates[ "ExpandLeft" ]); Assert.AreEqual < 文字列 >は、("ExpandDirectionStatesは"では、[visualStates"ExpandLeft"]); , visualStates[ "ExpandRight" ]); Assert.AreEqual < 文字列 >は、("ExpandDirectionStatesは"では、[visualStates"ExpandRight"]); ) を#endregionコントロール契約
注意してください管理契約は、[TemplateVisualState()]と[TemplatePart()]を付けたものの、理論的にはクラス階層を介して継承されない属性です。 サブクラスは再基本クラスのコントロール契約を宣言を通じて、彼らは通常は実際には、。 私たちのユニットテストクラスは、継承された、コントロールの契約を扱うため。
3番目の階層は、UIやイベントのテスト用です:
/ / / <summary> / / /インターフェイスは、パンダのメンバーをテストする仮想マシンに使用されます。 / / / </概要> パブリックインターフェイス IOverriddenExpander:IOverriddenHeaderedContentControl ( / / / <summary> / / /アクションを取得しますOnExpandedテスト。 / / / </概要> OverriddenMethodのExpandedActionsは(取得;) / / / <summary> / / /アクションを取得しますOnCollapsedテスト。 / / / </概要> OverriddenMethodのCollapsedActionsは(取得;) )
実際には通常3番目の階層一緒に使用されて4番目のパラレルクラス階層は:
- OverriddenFrameworkElement < - OverriddenControlの< - OverriddenContentControl
それはまだControls.Testing.Commonに実装されていませんが、Controls.Testingが良い例クラス何上記のように見て、どのように実装すればは、使用されるかを示すことですOverriddenTreeViewクラスを持っています。 私は2つのオーバーライドされたクラス階層、またはこのいずれかのそれらについての詳細記事を追加、変更のための別の記事を書くことができます。
Baseサポート
パブリック抽象クラス Baseサポート:SilverlightTest ( / /フィールド [は]をCompilerGenerated 民間の概要static int <DefaultVisualDelayInMilliseconds>のk__BackingField; / /メソッド 静的 Baseサポート(); ) 保護 Baseサポート(; visualDelay); 保護された無効EnqueueVisualDelay(int型 visualDelay); Action[] actions); 保護内部ボイド TestAsyncは(FrameworkElementは要素)アクション]アクションをparamsを 。 visualDelay, FrameworkElement element, params Action[] actions); 保護内部ボイド TestAsyncは(int型 visualDelay、FrameworkElementは要素)アクション]アクションをparamsを 。 Action<T>[] actions) where T: FrameworkElement; 保護内部ボイド TestSequenceAsync <T>は(IEnumerable <T>での要素は、)アクション<T>は[]アクションをparamsはここで、T:FrameworkElementは。 visualDelay, IEnumerable<T> elements, params Action<T>[] actions) where T: FrameworkElement; 保護内部ボイド TestSequenceAsync <T>は(int型 visualDelay、IEnumerable <T>で要素)アクション<T>は[]アクションをparamsはここで、T:FrameworkElementは。 Action[] actions); 保護内部ボイド TestTaskAsyncは(FrameworkElementは要素)アクション]アクションをparamsを 。 visualDelay, FrameworkElement element, params Action[] actions); 保護内部ボイド TestTaskAsyncは(int型 visualDelay、FrameworkElementは要素)アクション]アクションをparamsを 。 / /プロパティ 保護内部の概要static int DefaultVisualDelayInMillisecondsは([CompilerGenerated]を得る。[CompilerGenerated]を設定;) )
Baseサポートは、EnqueueCallback、EnqueueConditional、EnqueueSleep、EnqueueTestcompleteようWorkItemTestメソッドをラップし、TestAsyncとTestSequenceAsyncを2つの高レベルのユーティリティ機能を提供します。 各関数は、ミリ秒単位で遅延を受け取るオーバーロードを、ビジュアルツリーにいくつかの時間をテストアクションの間にレンダリングするために提供している。
依存プロパティユニットテスト
図1から別の明確なパターンは:Control.Testing.Commonクラス図は、すべてのテストクラスの実装ユニットテストに依存プロパティの彼らを紹介DependencyPropertyTest <T,P>ジェネリッククラスを使用します。 依存関係プロパティのPPPクラスXXXのためのユニットテストを追加する通常の3つの手順が含まれます:
- 定義プロパティ"DependencyPropertyTest <T,P> PPPProperty"クラスXXXTestで:
/ / / <summary> / / /テストを取得しますExpandDirection依存関係プロパティ。 / / / </概要> set; }取得保護 DependencyPropertyTest <Expander, ExpandDirection> ExpandDirectionPropertyは(; プライベート設定;)
- 作成PPPProperty XXXTestのコンストラクタで:
, "ExpandDirection" ) ExpandDirectionProperty = 新しい DependencyPropertyTest <Expander, ExpandDirection>( これは、"ExpandDirection") ( プロパティ= Expander.ExpandDirectionProperty、 初期化=初期化、 のDefaultValue = ExpandDirection.Down、 OtherValues = 新しい ExpandDirection [](ExpandDirection.Up、ExpandDirection.Left、ExpandDirection.Right)、 InvalidValues = 新しい辞書<ExpandDirection,タイプ> ( ((ExpandDirection)(-1)、typeof演算(ArgumentExceptionが))、 ((ExpandDirection)4、typeof演算(ArgumentExceptionが))、 ((ExpandDirection)5、typeof演算(ArgumentExceptionが))、 ((ExpandDirection)500、typeof演算(ArgumentExceptionが))、 (ArgumentException) }, ((ExpandDirection)intです 。MaxValueを、typeof演算(ArgumentExceptionが))、 (ArgumentException) } ((ExpandDirection)intです 。minvalueは、typeof演算(ArgumentExceptionが)) ) );
- GetDependencyPropertyTestsこの依存関係プロパティをオーバーライドの適切なテストを追加:
/ / ExpandDirectionPropertyテスト (ExpandDirectionProperty.CheckDefaultValueTest)tests.Add; (ExpandDirectionProperty.ChangeClrSetterTest)tests.Add; (ExpandDirectionProperty.ChangeSetValueTest)tests.Add; (ExpandDirectionProperty.ClearValueResetsDefaultTest)tests.Add; (ExpandDirectionProperty.InvalidValueFailsTest)tests.Add; (ExpandDirectionProperty.InvalidValueIsIgnoredTest)tests.Add; (ExpandDirectionProperty.CanBeStyledTest)tests.Add; (ExpandDirectionProperty.TemplateBindTest)tests.Add; (tests.Add ExpandDirectionProperty.ChangesVisualStateTest(ExpandDirection.Down、ExpandDirection.Up、"ExpandUp")); (tests.Add ExpandDirectionProperty.ChangesVisualStateTest(ExpandDirection.Up、ExpandDirection.Left、"ExpandLeft")); (tests.Add ExpandDirectionProperty.ChangesVisualStateTest(ExpandDirection.Left、ExpandDirection.Right、"ExpandRight")); (tests.Add ExpandDirectionProperty.ChangesVisualStateTest(ExpandDirection.Right、ExpandDirection.Down、"ExpandDown")); (ExpandDirectionProperty.SetXamlAttributeTest)tests.Add; (ExpandDirectionProperty.SetXamlElementTest)tests.Add;
また、/削除/依存関係プロパティをオーバーライド基本クラスGetDependencyPropertyTestsから継承されたのテストを追加、変更することができます:
tests.RemoveTests(HeaderProperty.TemplateBindTest); プロパティtests.Add(HeaderProperty.TemplateBindTest.Bug("TODO:この調査なぜコンテンツこれが失敗するここではないの。"));
ポストは、すでに思った以上に長いですが、私は今ここに停止するようにします。 ホープは、このヘルプは、私たちのユニットテストコードを理解し、高品質のソフトウェアを作成します。








最近のコメント