Silverlight Toolkit модульных тестов
Введение
Юнит-тестирование очень важно для качества разработки программного обеспечения. 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 проект, и общая картина дизайн наших модульных тестов:
Рисунок 1: Controls.Testing.Common Class Diagram
Параллельные иерархии классов
Это очень видно из вышеприведенной диаграммы классов, что Есть параллельные иерархии классов:
- FrameworkElement <- Контроль <- ContentControl
- FrameworkElementTest <- ControlTest <- ContentControlTest
- IOverriddenFrameworkElement <- IOverriddenControl <- IOverriddenContentControl
Первая иерархия цепочки наследования контроля классов, модульного тестирования.
Вторая иерархия цепочки наследования соответствующих классов модульного тестирования, параллельного классов элементов управления проходит испытания. Причиной для этого проекта является то, что, если это ContentControl управления, а затем ContentControlTest должны проверить все ControlTest делает. Есть некоторые общие закономерности в тест-дизайна класса. Предполагая, XXX наследует от YYY:
- XXXTest наследует от YYYTest. Если XXXTest не является абстрактным, оно помечается [TestClass] атрибута.
[TestClass] общественных частичный класс ExpanderTest: HeaderedContentControlTest {
- XXXTest представляет три новых свойства: DefaultXXXToTest, XXXsToTest, OverriddenXXXsToTest, и использовать их для реализации переопределение три свойства (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> / / / Получает экземпляр по умолчанию Expander (или производный тип), чтобы проверить. / / / </ Резюме> общественных виртуальных Expander DefaultExpanderToTest { получать { возвратить новый Expander (); } } / / / <summary> / / / Получает экземпляры Expander (или производные типы) для тестирования. / / / </ Резюме> общественных виртуальных IEnumerable ExpandersToTest <Expander> { получать { Выход возвращения DefaultExpanderToTest; i = 0; i < 4; i++) для (INT = 0; я <4; я + +) { Расширитель Расширитель = новый Expander { ExpandDirection = (ExpandDirection) я, IsExpanded = (я% 2 == 0) }; Выход возвращения расширителя; } } } / / / <summary> / / / Получает экземпляры IOverriddenContentControl (или производные типы) для тестирования. / / / </ Резюме> общественных виртуальных IEnumerable OverriddenExpandersToTest <IOverriddenExpander> { получать { доходность перерыва; } } # Endregion Расширители для тестирования
- XXXTest имеет открытый конструктор и перекрывает GetDependencyPropertyTest метода:
/ / / <summary> / / / Получить тесты свойства зависимостей. / / / </ Резюме> / / / <returns> Тесты свойства зависимостей. </ Возвращает> общественных переопределить IEnumerable GetDependencyPropertyTests <DependencyPropertyTestMethod> () { IList <DependencyPropertyTestMethod> тесты = TagInherited (базовый GetDependencyPropertyTests ().);
- XXXTest может переопределяет TemplatePartsAreDefined и TemplateVisualStateAreDefined методов, если XXX имеет новый договор управления определена, или изменяет контракт контракта его предков:
# Области управления контрактом / / / <summary> / / / Проверяет TemplateParts Control. / / / </ Резюме> [TestMethod] [Description ("Проверяет TemplateParts контролю и профилактике".)] общественного недействительными переопределить TemplatePartsAreDefined () { . IDictionary <строка, тип> = templateParts DefaultControlToTest.GetType () GetTemplateParts (); Assert.AreEqual (1, templateParts.Count); ]); Assert.AreSame (TypeOf (ToggleButton), templateParts ["ExpanderButton"]); } / / / <summary> / / / Проверка шаблона управления визуальных состояний. / / / </ Резюме> [TestMethod] [Description ("Проверка шаблона управления визуальные состояния".)] общественного недействительными переопределить TemplateVisualStatesAreDefined () { > visualStates = DefaultControlToTest.GetType().GetVisualStates(); . IDictionary <строка, строка> = visualStates DefaultControlToTest.GetType () GetVisualStates (); Assert.AreEqual (12, visualStates.Count); , visualStates[ "Normal" ]); Assert.AreEqual <строка> ("CommonStates", visualStates ["Normal"]); , visualStates[ "MouseOver" ]); Assert.AreEqual <строка> ("CommonStates", visualStates ["MouseOver"]); , visualStates[ "Pressed" ]); Assert.AreEqual <строка> ("CommonStates", visualStates ["прессованный"]); , visualStates[ "Disabled" ]); Assert.AreEqual <строка> ("CommonStates", visualStates ["Disabled"]); , visualStates[ "Focused" ]); Assert.AreEqual <строка> ("FocusStates", visualStates ["Focused"]); , 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 ()] атрибуты, не наследуются по иерархии классов в теории. В действительности они обычно, через контроль контракт подкласс повторного объявления базового класса. Таким образом, наши классы модульных тестов лечения контроль контракт как унаследованы.
Третья иерархия является для тестирования пользовательского интерфейса и событие:
/ / / <summary> / / / Интерфейс используется для проверки виртуальных членов Expander. / / / </ Резюме> общественных IOverriddenExpander интерфейса: IOverriddenHeaderedContentControl { / / / <summary> / / / Получает OnExpanded действия теста. / / / </ Резюме> OverriddenMethod ExpandedActions {получить;} / / / <summary> / / / Получает OnCollapsed действия теста. / / / </ Резюме> OverriddenMethod CollapsedActions {получить;} }
Существует на самом деле четвертой параллели иерархии класса, который обычно используется с третьей иерархии вместе:
- OverriddenFrameworkElement <- OverriddenControl <- OverriddenContentControl
Пока еще не реализованы в Controls.Testing.Common, но Controls.Testing имеет OverriddenTreeView класса, который является хорошим примером, чтобы показать, что над классами будет выглядеть и как они будут использоваться в случае их реализации. Я могу написать отдельный пост на два переопределены иерархии классов, или изменить это, чтобы добавить гораздо больше внимания, о них.
TestBase
открытый абстрактный класс TestBase: SilverlightTest { / / Поля [CompilerGenerated] частных статического Int <DefaultVisualDelayInMilliseconds> k__BackingField; / / Методы статических TestBase (); защищены TestBase (); 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>, Params Action <T> [] действия), где Т: FrameworkElement; visualDelay, IEnumerable<T> elements, params Action<T>[] actions) where T: FrameworkElement; защищенный внутренних недействительным TestSequenceAsync <T> (INT visualDelay, IEnumerable элементы <T>, Params Action <T> [] действия), где Т: FrameworkElement; Action[] actions); защищенный внутренних TestTaskAsync недействительными (FrameworkElement элемент, Params действий [] действия); visualDelay, FrameworkElement element, params Action[] actions); защищенный внутренних недействительным TestTaskAsync (INT visualDelay, FrameworkElement элемент, Params действий [] действия); / / Свойства охраняемые внутренние статические Int DefaultVisualDelayInMilliseconds {[CompilerGenerated] получить; [CompilerGenerated] набор;} }
TestBase обертывания WorkItemTest методы, такие как EnqueueCallback, EnqueueConditional, EnqueueSleep, EnqueueTestcomplete, а также обеспечить высокий уровень две вспомогательные функции TestAsync и TestSequenceAsync. Каждая функция имеет перегрузку, которая принимает задержки в миллисекундах, чтобы дать визуальное дерево некоторое время, чтобы сделать между ними тестовых воздействий.
Зависимые Test Unit собственности
Другой четкой картины из рисунка 1: Схема Control.Testing.Common класса является то, что все тестовые классы используют DependencyPropertyTest <T,P> универсальный класс для реализации модульного тестирования для свойств зависимостей они вводят. Добавление модульного теста для свойства зависимостей ППС класса ХХХ обычно включает в себя три этапа:
- Определить собственности "DependencyPropertyTest <T,P> PPPProperty" в классе XXXTest:
/ / / <summary> / / / Получает ExpandDirection свойства зависимости тест. / / / </ Резюме> set; } защищены DependencyPropertyTest <Expander, ExpandDirection> ExpandDirectionProperty {получить, частные набор;}
- Создать PPPProperty в конструкторе XXXTest это:
, "ExpandDirection" ) ExpandDirectionProperty = новый DependencyPropertyTest <Expander, ExpandDirection> (это, "ExpandDirection") { Недвижимость = Expander.ExpandDirectionProperty, Инициализатор Initializer =, DefaultValue = ExpandDirection.Down, OtherValues = новый ExpandDirection [] {ExpandDirection.Up, ExpandDirection.Left, ExpandDirection.Right}, InvalidValues = новый словарь <ExpandDirection, Type> { {(ExpandDirection) (-1), TypeOf (ArgumentException)}, {(ExpandDirection) 4, TypeOf (ArgumentException)}, {(ExpandDirection) 5, TypeOf (ArgumentException)}, {(ExpandDirection) 500, TypeOf (ArgumentException)}, (ArgumentException) }, {(ExpandDirection) внутр. MaxValue, TypeOf (ArgumentException)}, (ArgumentException) } {(ExpandDirection) внутр. MinValue, TypeOf (ArgumentException)} } };
- Добавить соответствующие тесты для этого свойства зависимостей в GetDependencyPropertyTests переопределить:
/ / ExpandDirectionProperty тесты tests.Add (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 (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")); tests.Add (ExpandDirectionProperty.SetXamlAttributeTest); tests.Add (ExpandDirectionProperty.SetXamlElementTest);
Вы также можете добавлять / удалять / изменять тесты на зависимость свойств, унаследованных от базовых классов в GetDependencyPropertyTests переопределить:
tests.RemoveTests (HeaderProperty.TemplateBindTest); tests.Add (HeaderProperty.TemplateBindTest.Bug ("TODO:. выяснить, почему это не удается здесь, но не для содержания имущества"));
Сообщение уже больше, чем я ожидал, поэтому я остановлюсь на данный момент. Надеюсь, это поможет вам понять нашу модульного тестирования кода и создания качественного программного обеспечения.








Последние комментарии