Архив

Архив для 'Test' Категория

Silverlight Toolkit модульных тестов

30 октября 2008 Нет комментариев

Введение

Юнит-тестирование очень важно для качества разработки программного обеспечения. Silverlight Toolkit обладает большим юнит-тестов, а также хорошие образцы. Silverlight Toolkit модульного тестирования проектов (Controls.Testing, Controls.Test.DataVisualization, Controls.Testing.Theming) используют Silverlight группы испытаний Framework (Microsoft.Silverlight.Testing.dll И Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight.dll) изобретен Jeff Wilcox , и класс модульного тестирования библиотеки (Controls.Testing.Common.dll) изобрел Тед Глаза. Вы можете найти много полезной информации о Silverlight Unit Test Framework из MSDN Code сайта галереи и блога Джеффа . Это сообщение говорит о том, главным образом блок Теда теста библиотеки классов выпущены в Silverlight Toolkit и показывает на примерах, как наши модульные тесты построены на вершине этой структуры.

Ниже приведена упрощенная схема класса, показывая некоторые классы в Controls.Testing.Common проект, и общая картина дизайн наших модульных тестов:

Silverlight Toolkit Unit Test Class Diagram

Рисунок 1: Controls.Testing.Common Class Diagram

Параллельные иерархии классов

Это совершенно ясно из вышеприведенной диаграммы классов, что существуют параллельные иерархии классов:

  1. FrameworkElement <- управление <- ContentControl
  2. FrameworkElementTest <- ControlTest <- ContentControlTest
  3. IOverriddenFrameworkElement <- IOverriddenControl <- IOverriddenContentControl

Первая иерархия цепочки наследования контроля классов, модульного тестирования.

Вторая иерархия цепочки наследования соответствующих классов модульного тестирования, параллельного контроля классы проходят испытания. Причиной для этого проекта в том, что если ContentControl является элементом управления, то ContentControlTest должны проверить все ControlTest делает. Есть некоторые общие закономерности в тест-дизайна класса. Предполагая, XXX наследует от YYY:

  • XXXTest наследует от YYYTest. Если XXXTest не является абстрактным, оно помечается [TestClass] атрибута.
      [TestClass]
     общественных частичный класс ExpanderTest: HeaderedContentControlTest
     { 

  • XXXTest представляет три новых свойства: DefaultXXXToTest, XXXsToTest, OverriddenXXXsToTest, и использовать их для реализации коррекции из трех свойств (DefaultYYYToTest, YYYsToTest, OverriddenYYYsToTest) представил его базовый класс YYYTest:
     public override HeaderedContentControl DefaultHeaderedContentControlToTest { get { return DefaultExpanderToTest; } } /// <summary> /// Gets instances of HeaderedContentControl (or derived types) to test. /// </summary> public override IEnumerable<HeaderedContentControl> HeaderedContentControlsToTest { get { return ExpandersToTest.OfType<HeaderedContentControl>(); } } /// <summary> /// Gets instances of IOverriddenContentControl (or derived types) to test. /// </summary> public override IEnumerable<IOverriddenHeaderedContentControl> OverriddenHeaderedContentControlsToTest { get { return OverriddenExpandersToTest.OfType<IOverriddenHeaderedContentControl>(); } } #endregion HeaderedContentControls to test #region Expanders to test /// <summary> /// Gets a default instance of Expander (or a derived type) to test. /// </summary> public virtual Expander DefaultExpanderToTest { get { return new Expander(); } } /// <summary> /// Gets instances of Expander (or derived types) to test. /// </summary> public virtual IEnumerable<Expander> ExpandersToTest { get { yield return DefaultExpanderToTest; for ( int i = 0; i < 4; i++) { Expander expander = new Expander { ExpandDirection = (ExpandDirection)i, IsExpanded = (i % 2 == 0) }; yield return expander; } } } /// <summary> /// Gets instances of IOverriddenContentControl (or derived types) to test. /// </summary> public virtual IEnumerable<IOverriddenExpander> OverriddenExpandersToTest { get { yield break ; } } #endregion Expanders to test # Регионе HeaderedContentControls для проверки / / / <summary> / / / Получает экземпляр по умолчанию HeaderedContentControl (или производный тип) для проверки / / / </ резюме> общественный коррекции HeaderedContentControl DefaultHeaderedContentControlToTest {get {return DefaultExpanderToTest;}}. / / / <summary> / / / Получает экземпляры HeaderedContentControl (или производных типов) для проверки / / / </ резюме> общественный коррекции IEnumerable <HeaderedContentControl> HeaderedContentControlsToTest. {get {возвращение ExpandersToTest.OfType <HeaderedContentControl> ();}} / / / <summary> / / / Получает экземпляры IOverriddenContentControl (или производных типов) для проверки / / / </ резюме> общественный коррекции IEnumerable <IOverriddenHeaderedContentControl> OverriddenHeaderedContentControlsToTest. {get {возвращение OverriddenExpandersToTest.OfType <IOverriddenHeaderedContentControl> ();}} # EndRegion HeaderedContentControls проверить # регионе расширителей для проверки / / / <summary> / / / Получает экземпляр по умолчанию Expander (или производный тип), чтобы проверить. / / / </ резюме> виртуальную общественность Expander DefaultExpanderToTest {get {return новый Expander ( );}} / / / <summary> / / / Получает экземпляры Expander (или производных типов) для проверки / / / </ резюме> виртуальную общественность IEnumerable <Expander> ExpandersToTest {get {получить возврат DefaultExpanderToTest;. для (INT я = 0, г <4, я + +) {Expander расширитель = новый Expander {ExpandDirection = (ExpandDirection) я, IsExpanded = (я% 2 == 0)}, выход расширитель возвращение;}}} / / / <summary> / / / Получает экземпляры IOverriddenContentControl (или производных типов) для проверки / / / </ резюме> виртуальную общественность IEnumerable <IOverriddenExpander> OverriddenExpandersToTest {get {доходность перерыва;}}. # EndRegion расширителей для тестирования 

  • XXXTest имеет открытый конструктор и перекрывает GetDependencyPropertyTest метод:
      / / / <summary>
     / / / Получить тесты свойства зависимостей.
     / / / </ Резюме>
     / / / <returns> Тесты свойства зависимостей. </ Возвращает>
     общественных коррекции IEnumerable GetDependencyPropertyTests <DependencyPropertyTestMethod> ()
     {
         IList <DependencyPropertyTestMethod> тесты = TagInherited (базовый GetDependencyPropertyTests ().); 

  • XXXTest мая отменяет TemplatePartsAreDefined и TemplateVisualStateAreDefined методы, если XXX имеет новый контракт контроль определен, договор или изменяет свой контракт предков:
     [TestMethod] [Description( "Verifies the Control's TemplateParts." )] public override void TemplatePartsAreDefined() { IDictionary< string , Type> templateParts = DefaultControlToTest.GetType().GetTemplateParts(); Assert.AreEqual(1, templateParts.Count); Assert.AreSame( typeof (ToggleButton), templateParts[ "ExpanderButton" ]); } /// <summary> /// Verify the control's template visual states. /// </summary> [TestMethod] [Description( "Verify the control's template visual states." )] public override void TemplateVisualStatesAreDefined() { IDictionary< string , string > visualStates = DefaultControlToTest.GetType().GetVisualStates(); Assert.AreEqual(12, visualStates.Count); Assert.AreEqual< string >( "CommonStates" , visualStates[ "Normal" ]); Assert.AreEqual< string >( "CommonStates" , visualStates[ "MouseOver" ]); Assert.AreEqual< string >( "CommonStates" , visualStates[ "Pressed" ]); Assert.AreEqual< string >( "CommonStates" , visualStates[ "Disabled" ]); Assert.AreEqual< string >( "FocusStates" , visualStates[ "Focused" ]); Assert.AreEqual< string >( "FocusStates" , visualStates[ "Unfocused" ]); Assert.AreEqual< string >( "ExpansionStates" , visualStates[ "Expanded" ]); Assert.AreEqual< string >( "ExpansionStates" , visualStates[ "Collapsed" ]); Assert.AreEqual< string >( "ExpandDirectionStates" , visualStates[ "ExpandDown" ]); Assert.AreEqual< string >( "ExpandDirectionStates" , visualStates[ "ExpandUp" ]); Assert.AreEqual< string >( "ExpandDirectionStates" , visualStates[ "ExpandLeft" ]); Assert.AreEqual< string >( "ExpandDirectionStates" , visualStates[ "ExpandRight" ]); } #endregion Control contract # Области управления контракта / / / <summary> / / / Проверяет TemplateParts управления. / / / </ Резюме> [TestMethod] [Description ("Проверка TemplateParts управления.")] Общественного недействительными коррекции TemplatePartsAreDefined () {IDictionary <строка , тип> = templateParts DefaultControlToTest.GetType () GetTemplateParts ();. Assert.AreEqual (1, templateParts.Count); Assert.AreSame (TypeOf (Выключатель), templateParts ["ExpanderButton"]);} / / / <summary> / / / Проверка шаблона управления визуальных состояний. / / / </ резюме> [TestMethod] [Description ("Проверка шаблона управления визуальных состояний.")] общественного недействительными коррекции TemplateVisualStatesAreDefined () {IDictionary <String, String> visualStates = DefaultControlToTest .. GetType () GetVisualStates (); Assert.AreEqual (12, visualStates.Count); Assert.AreEqual <строка> ("CommonStates", visualStates ["Normal"]); Assert.AreEqual <строка> ("CommonStates" visualStates ["MouseOver"]); Assert.AreEqual <строка> ("CommonStates", visualStates ["прессованный"]); Assert.AreEqual <строка> ("CommonStates", visualStates ["Disabled"]); Assert.AreEqual < строка> ("FocusStates", visualStates ["Focused"]); Assert.AreEqual <строка> ("FocusStates", visualStates ["Нецеленаправлен"]); Assert.AreEqual <строка> ("ExpansionStates", visualStates [«расширенная» ]); Assert.AreEqual <строка> ("ExpansionStates", visualStates ["Сложено"]); Assert.AreEqual <строка> ("ExpandDirectionStates", visualStates ["ExpandDown"]); Assert.AreEqual <строка> ("ExpandDirectionStates "visualStates [" ExpandUp "]); Assert.AreEqual <строка> (" ExpandDirectionStates ", visualStates [" ExpandLeft "]); Assert.AreEqual <строка> (" ExpandDirectionStates ", visualStates [" ExpandRight "]);} # Контракт EndRegion управления 

    Пожалуйста, обратите внимание, что, хотя управление контрактами, с аннотацией [TemplateVisualState ()] и [TemplatePart ()] атрибуты, не наследуются по иерархии классов в теории. В действительности они обычно через контроль контракт подкласс повторное объявление базового класса. Таким образом, наши классы модульных тестов лечения контроль договор наследству.

Третья иерархия для тестирования пользовательского интерфейса и событие:

 IOverriddenExpander : IOverriddenHeaderedContentControl { /// <summary> /// Gets the OnExpanded test actions. /// </summary> OverriddenMethod ExpandedActions { get; } /// <summary> /// Gets the OnCollapsed test actions. /// </summary> OverriddenMethod CollapsedActions { get; } } / / / <summary> / / / Interface используется для проверки виртуальных членов Expander / / / </ резюме> общественный IOverriddenExpander интерфейс.. IOverriddenHeaderedContentControl {/ / / <summary> / / / Получает OnExpanded действия тест / / / < / резюме> OverriddenMethod ExpandedActions {get;}. / / / <summary> / / / Получает OnCollapsed тестовых воздействий / / / </ резюме> OverriddenMethod CollapsedActions {get;}} 

Существует на самом деле четвертой параллели иерархии класса, который обычно используется с третьей иерархии вместе:

  1. OverriddenFrameworkElement <- OverriddenControl <- OverriddenContentControl

Это еще не реализована в Controls.Testing.Common, но Controls.Testing имеет OverriddenTreeView класс, который является хорошим примером показать, что выше классов будет выглядеть и как они будут использоваться в случае их реализации. Я могу написать отдельный пост для двух переопределить иерархии классов, или изменить это, чтобы добавить больше освещения в них.

TestBase

TestBase
Рисунок 2: TestBase

 [CompilerGenerated] private static int <DefaultVisualDelayInMilliseconds>k__BackingField; // общественный абстрактный класс TestBase: SilverlightTest {/ / Поля [CompilerGenerated] частных статических Int <DefaultVisualDelayInMilliseconds> k__BackingField / /  TestAsync( int visualDelay, FrameworkElement element, params Action[] actions); protected internal void TestSequenceAsync<T>(IEnumerable<T> elements, params Action<T>[] actions) where T: FrameworkElement; protected internal void TestSequenceAsync<T>( int visualDelay, IEnumerable<T> elements, params Action<T>[] actions) where T: FrameworkElement; protected internal void TestTaskAsync(FrameworkElement element, params Action[] actions); protected internal void TestTaskAsync( int visualDelay, FrameworkElement element, params Action[] actions); // Properties protected internal static int DefaultVisualDelayInMilliseconds { [CompilerGenerated] get; [CompilerGenerated] set; } } элементов, параметрами [действий] действий); защищен внутренний вакуум TestAsync (INT visualDelay, FrameworkElement элемент параметрами [действий] действий); защиты внутреннего недействительным TestSequenceAsync <T> (IEnumerable элементы <T>, параметрами действия <T> [] действия) где T: FrameworkElement, охраняемой внутренней недействительным TestSequenceAsync <T> (INT visualDelay, IEnumerable элементы <T>, параметрами действия <T> [] действия), где T: FrameworkElement, охраняемой внутренней TestTaskAsync недействительными (FrameworkElement элемент параметрами действий [] действия) ; охраняемой внутренней недействительным TestTaskAsync (INT visualDelay, FrameworkElement элемент параметрами действий [] действия) / / Свойства защиты внутреннего статического DefaultVisualDelayInMilliseconds Int {[CompilerGenerated] get; [CompilerGenerated] набор;}} 

TestBase обертывания WorkItemTest методы, такие как EnqueueCallback, EnqueueConditional, EnqueueSleep, EnqueueTestcomplete и обеспечивают две высокий уровень сервисных функций TestAsync и TestSequenceAsync. Каждая функция имеет перегрузку, которая принимает задержки в миллисекундах, чтобы дать визуальное дерево некоторое время, чтобы сделать тест между действиями.

Зависимые Test Unit недвижимости

Другая картина ясно из рисунка 1: Схема Control.Testing.Common класса является то, что все тестовые классы использовать DependencyPropertyTest <T,P> универсальный класс для реализации модульного тестирования для свойства зависимостей они представляют. Добавление модульных тестов для свойства зависимостей ППС класса XXX обычно включает в себя три этапа:

  1. Определить собственности "DependencyPropertyTest <T,P> PPPProperty" в классе XXXTest:
      / / / <summary>
     / / / Получает ExpandDirection свойства зависимостей тест.
     / / / </ Резюме>
     set; } защита DependencyPropertyTest <Expander, ExpandDirection> ExpandDirectionProperty {get; частный набор;} 

  2. Создать PPPProperty в конструкторе XXXTest в:
     , "ExpandDirection" ) { Property = Expander.ExpandDirectionProperty, Initializer = initializer, DefaultValue = ExpandDirection.Down, OtherValues = new ExpandDirection[] { ExpandDirection.Up, ExpandDirection.Left, ExpandDirection.Right }, InvalidValues = new Dictionary<ExpandDirection, Type> { { (ExpandDirection)(-1), typeof (ArgumentException) }, { (ExpandDirection)4, typeof (ArgumentException) }, { (ExpandDirection)5, typeof (ArgumentException) }, { (ExpandDirection)500, typeof (ArgumentException) }, { (ExpandDirection) int .MaxValue, typeof (ArgumentException) }, { (ExpandDirection) int .MinValue, typeof (ArgumentException) } } }; ExpandDirectionProperty = новый DependencyPropertyTest <Expander, ExpandDirection> (это, "ExpandDirection") {собственности = Expander.ExpandDirectionProperty, Initializer = инициализатор, DefaultValue = ExpandDirection.Down, OtherValues ​​= новый ExpandDirection [] {ExpandDirection.Up, ExpandDirection.Left, ExpandDirection. Право} InvalidValues ​​= новый словарь <ExpandDirection, Type> {{(ExpandDirection) (-1), TypeOf (ArgumentException)}, {(ExpandDirection) 4, TypeOf (ArgumentException)}, {(ExpandDirection) 5, TypeOf (ArgumentException) }, {(ExpandDirection) 500, TypeOf (ArgumentException)}, {(ExpandDirection) Int MaxValue, TypeOf (ArgumentException)}, {(ExpandDirection) Int MinValue, TypeOf (ArgumentException)}}}.. 

  3. Добавить соответствующие тесты для этого свойства зависимостей в GetDependencyPropertyTests коррекции:
     )); 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" )); tests.Add(ExpandDirectionProperty.SetXamlAttributeTest); tests.Add(ExpandDirectionProperty.SetXamlElementTest); / / ExpandDirectionProperty тесты tests.Add (ExpandDirectionProperty.CheckDefaultValueTest); tests.Add (ExpandDirectionProperty.ChangeClrSetterTest); tests.Add (ExpandDirectionProperty.ChangeSetValueTest); tests.Add (ExpandDirectionProperty.ClearValueResetsDefaultTest); tests.Add (ExpandDirectionProperty.InvalidValueFailsTest); тесты . Add (ExpandDirectionProperty.InvalidValueIsIgnoredTest); tests.Add (ExpandDirectionProperty.CanBeStyledTest); tests.Add (ExpandDirectionProperty.TemplateBindTest); tests.Add (ExpandDirectionProperty.ChangesVisualStateTest (ExpandDirection.Down, ExpandDirection.Up "ExpandUp")); тесты. Добавить (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")); tests.Add (ExpandDirectionProperty.SetXamlAttributeTest); tests.Add (ExpandDirectionProperty.SetXamlElementTest); 

Вы также можете добавлять / удалять / изменять тесты на зависимость свойства, унаследованные от базового класса в GetDependencyPropertyTests коррекции:

  tests.RemoveTests (HeaderProperty.TemplateBindTest);
 tests.Add (HeaderProperty.TemplateBindTest.Bug ("TODO. Выясните причины, почему это не поможет здесь, но не за содержание собственности")); 

Сообщение уже больше, чем я ожидал, поэтому я остановлюсь на данный момент. Надеюсь, это поможет вам понять наш код модульного тестирования и создания качественного программного обеспечения.

Technorati Теги: ,