Archives

Archive pour le «test» Catégorie

Test de Silverlight Toolkit Unité

30 octobre 2008 Pas de commentaires

Introduction

Test unitaire est très important pour le développement de logiciels de qualité. Le Silverlight Toolkit a des tests unitaires étendues, ainsi que des échantillons de bonnes. Silverlight Toolkit projets de tests unitaires (Controls.Testing, Controls.Test.DataVisualization, Controls.Testing.Theming) utiliser le framework Silverlight test unitaire (Microsoft.Silverlight.Testing.dll & Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight.dll) inventé par Jeff Wilcox , et une bibliothèque de classes unité de test (Controls.Testing.Common.dll) inventé par Ted Glaza. Vous pouvez trouver de nombreuses informations utiles sur cadre Silverlight test unitaire à partir de son site MSDN Code Gallery et du blog de ​​Jeff . Ce message parle surtout de la bibliothèque de Ted unité de test de classe publié dans le Silverlight Toolkit , et démontre par des exemples comment nos tests unitaires sont construits au-dessus de ce cadre.

Ci-dessous un diagramme de classes simplifié, montrant une partie des classes dans le projet Controls.Testing.Common, et le modèle de conception d'ensemble de nos tests unitaires:

Silverlight Toolkit Unit Test Class Diagram

Figure 1: Diagramme de classes Controls.Testing.Common

Hiérarchies de classes parallèles

Il est assez clair à partir du diagramme de classe ci-dessus qu'il ya des hiérarchies de classes parallèles:

  1. FrameworkElement <- <Contrôle - ContentControl
  2. FrameworkElementTest <- ControlTest <- ContentControlTest
  3. IOverriddenFrameworkElement <- IOverriddenControl <- IOverriddenContentControl

La première hiérarchie est la chaîne d'héritage des classes de contrôle étant unité de testés.

La seconde hiérarchie est la chaîne d'héritage de classes de tests unitaires correspondants, en parallèle avec les classes de contrôle en cours de test. La raison de cette conception est que si ContentControl est un contrôle, puis ContentControlTest devrait tester tout ControlTest fait. Il ya certaines tendances communes en matière de conception de classe de test. En supposant hérite XXX YYY à partir:

  • XXXTest hérite de YYYTest. Si XXXTest n'est pas abstraite, elle est marquée avec [TestClass] attribut.
      [TestClass]
     HeaderedContentControlTest: public partial class ExpanderTest
     { 

  • XXXTest introduit trois nouvelles propriétés: DefaultXXXToTest, XXXsToTest, OverriddenXXXsToTest, et les utiliser pour mettre en œuvre la dérogation des trois propriétés (DefaultYYYToTest, YYYsToTest, OverriddenYYYsToTest) introduites par sa classe de base YYYTest:
      # HeaderedContentControls région pour tester
     / / / <summary>
     / / / Obtient une instance par défaut de HeaderedContentControl (ou un type dérivé) à tester.
     / / / </ Summary>
     public override HeaderedContentControl DefaultHeaderedContentControlToTest
     {
         obtenir
         {
             retourner DefaultExpanderToTest;
         }
     }  
    
     / / / <summary>
     / / / Obtient des instances de HeaderedContentControl (ou types dérivés) pour tester.
     / / / </ Summary>
     public override IEnumerable <HeaderedContentControl> HeaderedContentControlsToTest
     {
         obtenir
         {
             retourner <HeaderedContentControl> ExpandersToTest.OfType ();
         }
     }  
    
     / / / <summary>
     / / / Obtient des instances de IOverriddenContentControl (ou types dérivés) pour tester.
     / / / </ Summary>
     public override IEnumerable <IOverriddenHeaderedContentControl> OverriddenHeaderedContentControlsToTest
     {
         obtenir
         {
             retourner <IOverriddenHeaderedContentControl> OverriddenExpandersToTest.OfType ();
         }
     }
     HeaderedContentControls endregion # pour tester  
    
     # Region Expandeurs pour tester
     / / / <summary>
     / / / Obtient une instance par défaut de Expander (ou un type dérivé) à tester.
     / / / </ Summary>
     publique Virtual Expander DefaultExpanderToTest
     {
         obtenir
         {
             retourner Expander nouvelle ();
         }
     }  
    
      / / / <summary>
     / / / Obtient des instances de Expander (ou types dérivés) pour tester.
     / / / </ Summary>
     publique ExpandersToTest virtuelle <Expander> IEnumerable
     {
         obtenir
         {
             céder retourner DefaultExpanderToTest;  
    
             i = 0; i < 4; i++) for (int i = 0; i <4; i + +)
             {
                 Expander extension = new Expander
                 {
                     ExpandDirection = (ExpandDirection) i,
                     = IsExpanded (% i 2 == 0)
                 };
                 céder expandeur retour;
             }
         }
     }  
    
     / / / <summary>
     / / / Obtient des instances de IOverriddenContentControl (ou types dérivés) pour tester.
     / / / </ Summary>
     publique OverriddenExpandersToTest virtuelle <IOverriddenExpander> IEnumerable
     {
         obtenir
         {
             céder briser;
         }
     }
     # Endregion Expandeurs pour tester 

  • XXXTest possède un constructeur public, et se substitue à GetDependencyPropertyTest méthode:
      / / / <summary>
     / / / Obtenir les tests de propriété de dépendance.
     / / / </ Summary>
     / / / <returns> Les tests de propriété de dépendance. </ Returns>
     publics GetDependencyPropertyTests override <DependencyPropertyTestMethod> IEnumerable ()
     {
         IList <DependencyPropertyTestMethod> tests = TagInherited (base GetDependencyPropertyTests ().); 

  • XXXTest peut remplace méthodes TemplatePartsAreDefined et TemplateVisualStateAreDefined, si XXX a contrat de contrôle nouvelle défini, ou modifie ses contrats contrat ancêtres:
      Contrat de commande # region
     / / / <summary>
     / / / Vérifie TemplateParts du contrôle.
     / / / </ Summary>
     [TestMethod]
     [Description ("Vérifie TemplateParts du contrôle.")]
     public override vide TemplatePartsAreDefined ()
     {
         IDictionary <string, type> = templateParts DefaultControlToTest.GetType () GetTemplateParts ().;
         Assert.AreEqual (1, templateParts.Count);
         ]); Assert.AreSame (typeof (ToggleButton), templateParts ["ExpanderButton"]);
     }  
    
     / / / <summary>
     / / / Vérifiez modèle du contrôle des états visuels.
     / / / </ Summary>
     [TestMethod]
     [Description ("Vérifiez modèle du contrôle états visuels.")]
     public override vide TemplateVisualStatesAreDefined ()
     {
         > visualStates = DefaultControlToTest.GetType().GetVisualStates(); . IDictionary <string, string> visualStates = DefaultControlToTest.GetType () GetVisualStates ();  
    
         Assert.AreEqual (12, visualStates.Count);  
    
         , visualStates[ "Normal" ]); Assert.AreEqual <> string ("CommonStates", visualStates ["Normal"]);
         , visualStates[ "MouseOver" ]); Assert.AreEqual <> string ("CommonStates", visualStates ["mouseover"]);
         , visualStates[ "Pressed" ]); Assert.AreEqual <> string ("CommonStates", visualStates ["Pressé"]);
         , visualStates[ "Disabled" ]); Assert.AreEqual <> string ("CommonStates", visualStates ["Désactivé"]);   
    
         , visualStates[ "Focused" ]); Assert.AreEqual <> string ("FocusStates", visualStates ["Focused"]);
         , visualStates[ "Unfocused" ]); Assert.AreEqual <> string ("FocusStates", visualStates ["Unfocused"]);
         , visualStates[ "Expanded" ]); Assert.AreEqual <> string ("ExpansionStates", visualStates ["élargi"]);
         , visualStates[ "Collapsed" ]); Assert.AreEqual <> string ("ExpansionStates", visualStates ["effondré"]);
         , visualStates[ "ExpandDown" ]); Assert.AreEqual <> string ("ExpandDirectionStates", visualStates ["ExpandDown"]);
         , visualStates[ "ExpandUp" ]); Assert.AreEqual <> string ("ExpandDirectionStates", visualStates ["ExpandUp"]);
         , visualStates[ "ExpandLeft" ]); Assert.AreEqual <> string ("ExpandDirectionStates", visualStates ["ExpandLeft"]);
         , visualStates[ "ExpandRight" ]); Assert.AreEqual <> string ("ExpandDirectionStates", visualStates ["ExpandRight"]);
     }
     Contrat n ° de commande endregion 

    S'il vous plaît noter que bien que les contrats de commande, annotées avec [TemplateVisualState ()] et [TemplatePart ()], les attributs ne sont pas héritées par hiérarchie de classes dans la théorie. En réalité, ils sont généralement, par le biais du contrat de contrôle classe de base sous-classe re-déclarer le. Donc, nos classes de tests unitaires traiter contrat de contrôle comme héréditaire.

La troisième hiérarchie est pour les tests d'assurance-chômage et de l'événement:

  / / / <summary>
 / / / Interface utilisée pour tester les membres virtuels de Expander.
 / / / </ Summary>
 IOverriddenExpander interface publique: IOverriddenHeaderedContentControl
 {
     / / / <summary>
     / / / Obtient les actions de test OnExpanded.
     / / / </ Summary>
     ExpandedActions OverriddenMethod {get;}
     / / / <summary>
     / / / Obtient les actions de test OnCollapsed.
     / / / </ Summary>
     CollapsedActions OverriddenMethod {get;}
 } 

Il ya effectivement une hiérarchie parallèle quatrième classe qui est habituellement utilisé avec la troisième hiérarchie entre eux:

  1. OverriddenFrameworkElement <- OverriddenControl <- OverriddenContentControl

Il n'est pas encore mis en œuvre dans Controls.Testing.Common, mais a de la classe Controls.Testing OverriddenTreeView, qui est un bon exemple pour montrer ce que les classes ci-dessus ressemblerait et comment elles seraient utilisées, si elles sont appliquées. Je peux écrire un poste distinct pour les deux hiérarchies de classes surchargées, ou de modifier celui-ci d'ajouter une couverture plus large à leur sujet.

TestBase

TestBase
Figure 2: TestBase

  publique TestBase classe abstraite: SilverlightTest
 {
     / / Champs
     [CompilerGenerated]
     private static int <DefaultVisualDelayInMilliseconds> k__BackingField;

     / / Méthodes
     TestBase statique ();
     protégée TestBase ();
     visualDelay); EnqueueVisualDelay protected void (int visualDelay);
     Action[] actions); protégée TestAsync vide interne (élément FrameworkElement, Action params [] actions);
     visualDelay, FrameworkElement element, params Action[] actions); protected void interne TestAsync (int visualDelay, élément FrameworkElement, Action params [] actions);
     Action<T>[] actions) where T: FrameworkElement; protected internal vide TestSequenceAsync <T> (IEnumerable éléments <T>, params action <T> [] actions)  T: FrameworkElement;
     visualDelay, IEnumerable<T> elements, params Action<T>[] actions) where T: FrameworkElement; protected internal vide TestSequenceAsync <T> (int visualDelay, IEnumerable éléments <T>, params action <T> [] actions)  T: FrameworkElement;
     Action[] actions); protégée TestTaskAsync vide interne (élément FrameworkElement, Action params [] actions);
     visualDelay, FrameworkElement element, params Action[] actions); protected void interne TestTaskAsync (int visualDelay, élément FrameworkElement, Action params [] actions);

     / / Propriétés
     protégées internes statiques DefaultVisualDelayInMilliseconds int {[CompilerGenerated] obtenir; [CompilerGenerated] set;}
 } 

TestBase enveloppe WorkItemTest méthodes comme EnqueueCallback, EnqueueConditional, EnqueueSleep, EnqueueTestcomplete, et fournir deux de haut niveau les fonctions d'utilité TestAsync et TestSequenceAsync. Chaque fonction a une surcharge qui prend un retard en millisecondes, pour donner un peu de temps arborescence d'éléments visuels pour rendre entre les actions de test.

Dépendant de test unitaire de la propriété

Une autre tendance claire de la figure 1: Diagramme de classes Control.Testing.Common, c'est que toutes les classes de test utilisent DependencyPropertyTest classe <T,P> générique de test unitaire pour la mise en œuvre des propriétés de dépendance qu'ils introduisent. Ajout de test unitaire pour la propriété de dépendance PPP de la classe XXX comprend généralement trois étapes:

  1. Définir la propriété «DependencyPropertyTest <T,P> PPPProperty" dans la classe XXXTest:
      / / / <summary>
     / / / Obtient la propriété de test ExpandDirection dépendance.
     / / / </ Summary>
     set; } protégée DependencyPropertyTest <Expander, ExpandDirection> ExpandDirectionProperty {get; set privé;} 

  2. Créer PPPProperty dans le constructeur de XXXTest:
      , "ExpandDirection" ) ExpandDirectionProperty = new DependencyPropertyTest <Expander, ExpandDirection> (this, "ExpandDirection")
     {
         Propriété = Expander.ExpandDirectionProperty,
         Initialiseur = Initializer,
         DefaultValue = ExpandDirection.Down,
         OtherValues ​​= ExpandDirection nouvelle [] {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)},
             (ArgumentException) }, {(ExpandDirection) int. MaxValue, typeof (ArgumentException)},
             (ArgumentException) } {(ExpandDirection) int. MinValue, typeof (ArgumentException)}
         }
     }; 

  3. Ajouter des tests appropriés pour cette propriété de dépendance dans GetDependencyPropertyTests dérogation:
      / / Tests de 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); 

Vous pouvez également ajouter / supprimer / modifier des tests pour des propriétés de dépendance héritées des classes de base dans GetDependencyPropertyTests dérogation:

  tests.RemoveTests (HeaderProperty.TemplateBindTest);
 tests.Add (HeaderProperty.TemplateBindTest.Bug ("TODO:. chercher à savoir pourquoi cela ne fonctionne pas ici, mais pas pour la propriété Content")); 

Le poste est déjà plus que ce que j'attendais, je vais donc m'arrêter ici pour le moment. J'espère que cela vous aider à comprendre notre code de test unitaire et de créer des logiciels de qualité.