Archivo

Archive for the 'Test' Categoría

Silverlight Toolkit de pruebas unitarias

30 de octubre 2008 No hay comentarios

Introducción

Prueba de la unidad es muy importante para el desarrollo de la calidad del software. El kit de herramientas de Silverlight tiene pruebas exhaustivas unidad, así como muestras de buena. Silverlight Toolkit proyectos de prueba de unidad (Controls.Testing, Controls.Test.DataVisualization, Controls.Testing.Theming) utilizar la Unidad de Silverlight Test Framework (Microsoft.Silverlight.Testing.dll y Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight.dll) inventado por Jeff Wilcox , y una prueba de unidad de biblioteca de clases (Controls.Testing.Common.dll) inventado por Ted Glaza. Usted puede encontrar mucha información útil acerca de Silverlight Marco de pruebas unitarias de su sitio de MSDN Code Gallery y blog de ​​Jeff . Este post sobre todo habla de la biblioteca de la clase de Ted unidad de prueba publicado en el kit de herramientas de Silverlight , y demuestra con ejemplos de cómo nuestras pruebas de unidad se construyen en la parte superior de ese marco.

A continuación se muestra un diagrama de clases simplificado, que muestra algunas de las clases en el proyecto de Controls.Testing.Common, y el patrón de diseño general de las pruebas de nuestra unidad:

Silverlight Toolkit Unit Test Class Diagram

Figura 1: Diagrama de clases Controls.Testing.Common

Las jerarquías paralelas de clase

Es bastante claro a partir de diagramas de clases por encima de la existencia de jerarquías paralelas de clase:

  1. FrameworkElement <- Control <- ContentControl
  2. FrameworkElementTest <- ControlTest <- ContentControlTest
  3. IOverriddenFrameworkElement <- IOverriddenControl <- IOverriddenContentControl

La primera jerarquía es la cadena de herencia de clases de control que la unidad probada.

La segunda jerarquía es la cadena de herencia de clases correspondiente unidad de prueba, en paralelo con las clases de control se está probando. La razón de este diseño es que si ContentControl es un control, entonces debe probar todo lo que ContentControlTest ControlTest hace. Hay algunos patrones comunes en el diseño de la prueba de clase. Suponiendo que hereda de la XXX YYY:

  • XXXTest hereda de YYYTest. Si XXXTest no es abstracto, que está marcado con [TestClass] atributo.
      [TestClass]
     pública parcial de la clase ExpanderTest: HeaderedContentControlTest
     { 

  • XXXTest introduce tres nuevas propiedades: DefaultXXXToTest, XXXsToTest, OverriddenXXXsToTest, y los utilizan para poner en práctica la anulación de las tres propiedades (DefaultYYYToTest, YYYsToTest, OverriddenYYYsToTest) presentado por su YYYTest clase base:
      # HeaderedContentControls región para poner a prueba
     / / / <summary>
     / / / Obtiene una instancia predeterminada de HeaderedContentControl (o un tipo derivado) para poner a prueba.
     / / / </ Summary>
     público superior HeaderedContentControl DefaultHeaderedContentControlToTest
     {
         obtener
         {
             volver DefaultExpanderToTest;
         }
     }  
    
     / / / <summary>
     / / / Obtiene los casos de HeaderedContentControl (o tipos derivados) para poner a prueba.
     / / / </ Summary>
     público superior IEnumerable HeaderedContentControlsToTest <HeaderedContentControl>
     {
         obtener
         {
             volver <HeaderedContentControl> ExpandersToTest.OfType ();
         }
     }  
    
     / / / <summary>
     / / / Obtiene los casos de IOverriddenContentControl (o tipos derivados) para poner a prueba.
     / / / </ Summary>
     público superior IEnumerable OverriddenHeaderedContentControlsToTest <IOverriddenHeaderedContentControl>
     {
         obtener
         {
             volver <IOverriddenHeaderedContentControl> OverriddenExpandersToTest.OfType ();
         }
     }
     # Endregion HeaderedContentControls para poner a prueba  
    
     # Region expansores para poner a prueba
     / / / <summary>
     / / / Obtiene una instancia predeterminada de Expander (o un tipo derivado) para poner a prueba.
     / / / </ Summary>
     pública Virtual Expander DefaultExpanderToTest
     {
         obtener
         {
             volver Expander nuevo ();
         }
     }  
    
      / / / <summary>
     / / / Obtiene los casos de Expander (o tipos derivados) para poner a prueba.
     / / / </ Summary>
     pública ExpandersToTest virtuales <Expander> IEnumerable
     {
         obtener
         {
             maximizar su retorno DefaultExpanderToTest;  
    
             i = 0; i < 4; i++) for (int i = 0; i <4; i + +)
             {
                 Expansor expansor = new Expander
                 {
                     ExpandDirection = (ExpandDirection) i,
                     = IsExpanded (i% 2 == 0)
                 };
                 maximizar su retorno de expansión;
             }
         }
     }  
    
     / / / <summary>
     / / / Obtiene los casos de IOverriddenContentControl (o tipos derivados) para poner a prueba.
     / / / </ Summary>
     pública OverriddenExpandersToTest virtuales <IOverriddenExpander> IEnumerable
     {
         obtener
         {
             yield break;
         }
     }
     # Endregion expansores para poner a prueba 

  • XXXTest tiene un constructor público y anula GetDependencyPropertyTest método:
      / / / <summary>
     / / / Obtener las pruebas de propiedad de dependencia.
     / / / </ Summary>
     / / / <returns> Las pruebas de propiedad de dependencia. </ Returns>
     público superior GetDependencyPropertyTests <DependencyPropertyTestMethod> IEnumerable ()
     {
         IList <DependencyPropertyTestMethod> pruebas = TagInherited (base GetDependencyPropertyTests ().) 

  • XXXTest pueden sustituya los métodos TemplatePartsAreDefined y TemplateVisualStateAreDefined, si XXX tiene contrato nuevo control definido, o modifica su contrato antepasados ​​contrato:
      # Region de control del contrato
     / / / <summary>
     / / / Verifica TemplateParts del Control.
     / / / </ Summary>
     [TestMethod]
     [Description ("Verifica TemplateParts del Control").]
     public override void TemplatePartsAreDefined ()
     {
         . IDictionary <cadena, escriba> = templateParts DefaultControlToTest.GetType () GetTemplateParts ();
         Assert.AreEqual (1, templateParts.Count);
         ]); Assert.AreSame (typeof (ToggleButton), templateParts ["ExpanderButton"]);
     }  
    
     / / / <summary>
     / / / Verificar el control de la plantilla de estados visuales.
     / / / </ Summary>
     [TestMethod]
     [Description ("Verifique que el control de la plantilla de estados visuales").]
     public override void TemplateVisualStatesAreDefined ()
     {
         > visualStates = DefaultControlToTest.GetType().GetVisualStates(); . IDictionary <cadena, cadena de> = 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 ["presionado"]);
         , visualStates[ "Disabled" ]); Assert.AreEqual <> string ("CommonStates", visualStates ["Disabled"]);   
    
         , visualStates[ "Focused" ]); Assert.AreEqual <> string ("FocusStates", visualStates ["Centrado"]);
         , visualStates[ "Unfocused" ]); Assert.AreEqual <> string ("FocusStates", visualStates ["Desenfocado"]);
         , visualStates[ "Expanded" ]); Assert.AreEqual <> string ("ExpansionStates", visualStates ["ampliado"]);
         , visualStates[ "Collapsed" ]); Assert.AreEqual <> string ("ExpansionStates", visualStates ["colapsados"]);
         , 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"]);
     }
     # Endregion Control de contrato 

    Tenga en cuenta que aunque los contratos de control, con la anotación [TemplateVisualState ()] y [TemplatePart ()] atributos, no se heredan a través de la jerarquía de clases en la teoría. En realidad, suelen ser, a través de contrato de control subclase volver a declarar la clase base. Así que nuestras clases de prueba de la unidad de control como el tratamiento de contrato heredado.

La tercera jerarquía es para probar la interfaz de usuario y eventos:

  / / / <summary>
 / / / Interfaz que se utiliza para poner a prueba los miembros virtuales de Expander.
 / / / </ Summary>
 IOverriddenExpander interfaz pública: IOverriddenHeaderedContentControl
 {
     / / / <summary>
     / / / Obtiene las acciones OnExpanded prueba.
     / / / </ Summary>
     ExpandedActions OverriddenMethod {get;}
     / / / <summary>
     / / / Obtiene las acciones OnCollapsed prueba.
     / / / </ Summary>
     CollapsedActions OverriddenMethod {get;}
 } 

En realidad, hay una jerarquía de cuarto curso paralelo que se utiliza generalmente con la tercera jerarquía en conjunto:

  1. OverriddenFrameworkElement <- OverriddenControl <- OverriddenContentControl

No se ha implementado en Controls.Testing.Common, pero tiene clase Controls.Testing OverriddenTreeView, que es un buen ejemplo para mostrar lo que las clases anterior quedaría así y cómo se iban a utilizar, si se aplican. Puedo escribir un post aparte para los dos jerarquías de clases se reemplaza, o modificar ésta para añadir más cobertura sobre ellos.

TestBase

TestBase
Figura 2: TestBase

  public abstract TestBase clase: SilverlightTest
 {
     / / Campos
     [CompilerGenerated]
     private static int <DefaultVisualDelayInMilliseconds> k__BackingField;

     / / Métodos
     TestBase estático ();
     protegidos TestBase ();
     visualDelay); protected void EnqueueVisualDelay (visualDelay int);
     Action[] actions); TestAsync protegidos vacío interno (elemento FrameworkElement, Acción params [] acciones);
     visualDelay, FrameworkElement element, params Action[] actions); protected internal vacío TestAsync (int visualDelay, elemento FrameworkElement, Acción params [] acciones);
     Action<T>[] actions) where T: FrameworkElement; protected internal vacío TestSequenceAsync <T> (IEnumerable elementos <T>, params Acción <T> [] acciones), donde T: FrameworkElement;
     visualDelay, IEnumerable<T> elements, params Action<T>[] actions) where T: FrameworkElement; protected internal vacío TestSequenceAsync <T> (int visualDelay, IEnumerable elementos <T>, params Acción <T> [] acciones), donde T: FrameworkElement;
     Action[] actions); TestTaskAsync protegidos vacío interno (elemento FrameworkElement, Acción params [] acciones);
     visualDelay, FrameworkElement element, params Action[] actions); protected internal vacío TestTaskAsync (int visualDelay, elemento FrameworkElement, Acción params [] acciones);

     / / Propiedades
     protected internal DefaultVisualDelayInMilliseconds static int {[CompilerGenerated] obtener, [CompilerGenerated] set;}
 } 

TestBase envuelve WorkItemTest métodos como EnqueueCallback, EnqueueSleep EnqueueConditional, EnqueueTestcomplete, y proporcionan dos de alto nivel de utilidad y funciones TestAsync TestSequenceAsync. Cada función tiene una sobrecarga que tiene un retraso en milisegundos, para dar árbol visual algo de tiempo para hacer que entre las acciones de la prueba.

Propiedad depende de pruebas unitarias

Otra tendencia clara en la figura 1: Diagrama de Clase Control.Testing.Common es que todas las clases de prueba de uso DependencyPropertyTest clase genérica <T,P> para poner a prueba la aplicación de unidad de las propiedades de dependencia que introducen. Adición de prueba de la unidad de propiedad de dependencia de la clase XXX PPP por lo general incluye tres pasos:

  1. Definir la propiedad "DependencyPropertyTest <T,P> PPPProperty" en la clase XXXTest:
      / / / <summary>
     / / / Obtiene la dependencia ExpandDirection prueba de propiedad.
     / / / </ Summary>
     set; } protegidos DependencyPropertyTest <Expander, ExpandDirection> ExpandDirectionProperty {get; set privado;} 

  2. Crear PPPProperty en el constructor de XXXTest:
      , "ExpandDirection" ) ExpandDirectionProperty = new DependencyPropertyTest <Expander, ExpandDirection> (this, "ExpandDirection")
     {
         Property = Expander.ExpandDirectionProperty,
         Inicializador inicializador =,
         DefaultValue = ExpandDirection.Down,
         OtherValues ​​ExpandDirection = new [] {ExpandDirection.Up, ExpandDirection.Left, ExpandDirection.Right}
         InvalidValues ​​= new Diccionario <ExpandDirection, <Tipo
         {
             {(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. Añadir las pruebas adecuadas para esta propiedad de dependencia en GetDependencyPropertyTests anular:
      / / ExpandDirectionProperty pruebas
     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); 

También puede añadir / quitar / modificar las pruebas de las propiedades de dependencia heredada de las clases base en GetDependencyPropertyTests anular:

  tests.RemoveTests (HeaderProperty.TemplateBindTest);
 tests.Add (HeaderProperty.TemplateBindTest.Bug ("TODO:. investigar por qué esto no funciona aquí, pero no para la propiedad Content")); 

El puesto es ya más larga de lo que esperaba, así que me detendré aquí por ahora. Espero que esto ayudará a entender nuestro código de prueba la unidad y crear software de calidad.