Abilitare il test codificato dell'interfaccia utente per i controlli

Il controllo può essere verificato più facilmente se si implementa il supporto per il framework di test codificati dell'interfaccia utente.È possibile aggiungere gradualmente livelli crescenti di supporto.È possibile iniziare supportando la registrazione, la riproduzione, e la convalida delle proprietà.È possibile compilare su quello per consentire al generatore di test codificati dell'interfaccia utente di riconoscere le proprietà personalizzate del controllo, e di fornire le classi personalizzate per accedere a quelle proprietà dal codice generato.È inoltre possibile facilitare il generatore di test codificati dell'interfaccia utente ad acquisire le azioni in una modalità che si avvicina di più allo scopo dell'azione registrata.

In questo argomento:

  1. Supportare registrazione, riproduzione, e convalida delle proprietà implementando l'accessibilità.

  2. Supportare la convalida della proprietà personalizzata implementando un provider di proprietà

  3. Supportare la generazione di codice implementando una classe per accedere alle proprietà personalizzate

  4. Supportare le azioni Intent-Aware implementando un Filtro Azione

CUIT_Full

Supportare registrazione, riproduzione, e convalida delle proprietà implementando l'accessibilità.

Il generatore di test codificati dell'interfaccia utente acquisisce informazioni sui controlli incontrati durante la registrazione e quindi genera il codice per riprodurre quella sessione.Se il controllo non supporta l'accessibilità, il generatore di test codificati dell'interfaccia utente acquisisce le azioni (quali i clic del mouse) utilizzando le coordinate dello schermo.Quando il test viene riprodotto, il codice generato emetterà i clic del mouse nelle stesse coordinate dello schermo.Se il controllo viene visualizzato in un punto diverso dello schermo quando il test viene riprodotto, il codice generato non sarà in grado di eseguire tale azione nel controllo.Questi errori si possono verificare se il test viene riprodotto in diverse configurazioni dello schermo, in ambienti diversi, o dopo che sono state apportate modifiche al layout dell'interfaccia utente.

CUIT_RecordNoSupport

Se si implementa l'accessibilità, tuttavia, il generatore di test codificati la utilizzerà per acquisire informazioni sul controllo quando registra un test e genera il codice.Quindi, quando si esegue il test, il codice generato riprodurrà tali eventi sul controllo, anche se è altrove nell'interfaccia utente.Gli autori del test potranno inoltre creare le asserzioni utilizzando le proprietà di base del controllo.

CUIT_Record

Hh552522.collapse_all(it-it,VS.110).gifPer supportare registrazione e riproduzione, convalida della proprietà, e navigazione per un controllo di Windows form

Implementare l'accessibilità per il controllo come descritto nella procedura seguente, e descritto in dettaglio in AccessibleObject.

CUIT_Accessible

  1. Implementare una classe che derivi da Control.ControlAccessibleObject, ed eseguire l'override della proprietà AccessibilityObject per restituire un oggetto della classe.

    public partial class ChartControl : UserControl
    {
        // Overridden to return the custom AccessibleObject for the control.
        protected override AccessibleObject CreateAccessibilityInstance()
        {
            return new ChartControlAccessibleObject(this);
        }
    
        // Inner class ChartControlAccessibleObject represents accessible information
        // associated with the ChartControl and is used when recording tests.
        public class ChartControlAccessibleObject : ControlAccessibleObject
        {
            ChartControl myControl;
            public ChartControlAccessibleObject(ChartControl ctrl)
                : base(ctrl)
            {
                myControl = ctrl;
            }
        }
    }
    
  2. Eseguire l'override dei metodi e delle proprietà Role, State, GetChild e GetChildCount dell'oggetto accessibile.

  3. Implementare un altro oggetto accessibilità per il controllo figlio ed eseguire l'override delle proprietà AccessibilityObject del controllo figlio per restituire tale oggetto accessibilità.

  4. Eseguire l'override delle proprietà e dei metodi Bounds, Name, Parent, Role, State, Navigate, e Select per l'oggetto accessibilità del controllo figlio.

[!NOTA]

Questo argomento inizia con l'esempio di accessibilità in AccessibleObject in questa procedura, e quindi le compilazioni su quella nelle procedure restanti.Se si desidera creare una versione funzionante dell'esempio di accessibilità, creare un'applicazione console e quindi sostituire il codice in Program.cs con il codice di esempio.Sarà necessario aggiungere riferimenti a Accessibilità, System.Drawing, e System.Windows.Forms.È necessario modificare Incorpora tipi di interoperabilità per l'Accessibilità su False per eliminare un avviso di compilazione.È possibile modificare il tipo di output del progetto da Applicazione console ad Applicazione Windows in modo che non venga visualizzata una finestra della console quando si esegue l'applicazione.

Supportare la convalida della proprietà personalizzata implementando un provider di proprietà

Dopo aver implementato il supporto di base per la registrazione, riproduzione, e convalida delle proprietà, è possibile rendere disponibili le proprietà personalizzate del controllo ai test codificati dell'interfaccia utente mediante l'implementazione di un plug-in UITestPropertyProvider.Ad esempio, la procedura seguente crea un provider di proprietà che consente ai test codificati dell'interfaccia utente di accedere alla proprietà di stato dei controlli figlio CurveLegend del controllo grafico.

CUIT_CustomProps

Hh552522.collapse_all(it-it,VS.110).gifPer supportare la convalida delle proprietà personalizzate

CUIT_Props

  1. Eseguire l'override della proprietà Description dell'oggetto accessibile curve legend per passare valori di proprietà avanzate nella stringa di descrizione, separati dalla descrizione principale (e tra loro se si stanno implementando più proprietà) con il punto e virgola (;).

    public class CurveLegendAccessibleObject : AccessibleObject
    {
        // add the state property value to the description
        public override string Description
        {
            get
            {
                // Add “;” and the state value to the end
                // of the curve legend’s description
                return "CurveLegend; " + State.ToString();
            }
        }
    }
    
  2. Creare un pacchetto di estensione di test dell'interfaccia utente per il controllo creando un progetto libreria di classi e aggiungere riferimenti a Accessibilità, Microsoft.VisualStudio.TestTools.UITesting, Microsoft.VisualStudio.TestTools.UITest.Common, e Microsoft.VisualStudio.TestTools.Extension.Modificare Incorpora tipi di interoperabilità per l'Accessibilità su False.

  3. Aggiungere una classe di provider di proprietà che sia derivata da UITestPropertyProvider.

    using System;
    using System.Collections.Generic;
    using Accessibility;
    using Microsoft.VisualStudio.TestTools.UITesting;
    using Microsoft.VisualStudio.TestTools.UITest.Extension;
    using Microsoft.VisualStudio.TestTools.UITesting.WinControls;
    using Microsoft.VisualStudio.TestTools.UITest.Common;
    
    namespace ChartControlExtensionPackage
    {
        public class ChartControlPropertyProvider : UITestPropertyProvider
        {
        }
    }
    
  4. Implementare il provider di proprietà inserendo i nomi di proprietà e i descrittori di proprietà in Dictionary<TKey, TValue>.

    // Define a map of property descriptors for CurveLegend
    private static Dictionary<string, UITestPropertyDescriptor> curveLegendPropertiesMap = null;
    private static Dictionary<string, UITestPropertyDescriptor> CurveLegendPropertiesMap
    {
        get
        {
            if (curveLegendPropertiesMap == null)
            {
                UITestPropertyAttributes read =
                    UITestPropertyAttributes.Readable |
                    UITestPropertyAttributes.DoNotGenerateProperties;
                curveLegendPropertiesMap =
                    new Dictionary<string, UITestPropertyDescriptor>
                        (StringComparer.OrdinalIgnoreCase);
                curveLegendPropertiesMap.Add("State",
                    new UITestPropertyDescriptor(typeof(string), read));
            }
            return curveLegendPropertiesMap;
        }
    }
    
    // return the property descriptor
    public override UITestPropertyDescriptor GetPropertyDescriptor(UITestControl uiTestControl, string propertyName)
    {
        return CurveLegendPropertiesMap[propertyName];
    }
    
    // return the property names
    public override ICollection<string> GetPropertyNames(UITestControl uiTestControl)
    {
        if (uiTestControl.ControlType.NameEquals("Chart") || uiTestControl.ControlType.NameEquals("Text"))
        {
            // the keys of the property map are the collection of property names
            return CurveLegendPropertiesMap.Keys;
        }
    
        // this is not my control
        throw new NotSupportedException();
    }
    
    // Get the property value by parsing the accessible description
    public override object GetPropertyValue(UITestControl uiTestControl, string propertyName)
    {
        if (String.Equals(propertyName, "State", StringComparison.OrdinalIgnoreCase))
        {
            object[] native = uiTestControl.NativeElement as object[];
            IAccessible acc = native[0] as IAccessible;
    
            string[] descriptionTokens = acc.accDescription.Split(new char[] { ';' });
            return descriptionTokens[1];
        }
    
        // this is not my control
        throw new NotSupportedException();
    }
    
  5. Eseguire l'override di UITestPropertyProvider.GetControlSupportLevel per indicare che l'assembly fornisce supporto specifico del controllo per il controllo e i suoi elementi figlio.

    public override int GetControlSupportLevel(UITestControl uiTestControl)
    {
        // For MSAA, check the control type
        if (string.Equals(uiTestControl.TechnologyName, "MSAA",
            StringComparison.OrdinalIgnoreCase) &&
            (uiTestControl.ControlType == "Chart"||uiTestControl.ControlType == "Text"))
        {
            return (int)ControlSupport.ControlSpecificSupport;
        }
    
        // This is not my control, so return NoSupport
        return (int)ControlSupport.NoSupport;
    }
    
  6. Eseguire l'override dei rimanenti metodi astratti di Microsoft.VisualStudio.TestTools.UITesting.UITestPropertyProvider.

    public override string[] GetPredefinedSearchProperties(Type specializedClass)
    {
        throw new NotImplementedException();
    }
    
    public override Type GetSpecializedClass(UITestControl uiTestControl)
    {
        throw new NotImplementedException();
    }
    
    public override Type GetPropertyNamesClassType(UITestControl uiTestControl)
    {
        throw new NotImplementedException();
    }
    
    public override void SetPropertyValue(UITestControl uiTestControl, string propertyName, object value)
    {
        throw new NotImplementedException();
    }
    
    public override string GetPropertyForAction(UITestControl uiTestControl, UITestAction action)
    {
        throw new NotImplementedException();
    }
    
    public override string[] GetPropertyForControlState(UITestControl uiTestControl, ControlStates uiState, out bool[] stateValues)
    {
        throw new NotImplementedException();
    }
    
    
    
    
    
  7. Aggiungere una classe del pacchetto di estensione che sia derivata da UITestExtensionPackage.

    using System;
    using Microsoft.VisualStudio.TestTools.UITesting;
    using Microsoft.VisualStudio.TestTools.UITest.Extension;
    using Microsoft.VisualStudio.TestTools.UITest.Common;
    
    namespace ChartControlExtensionPackage
    {
        internal class ChartControlExtensionPackage : UITestExtensionPackage
        {
        }
    }
    
  8. Definire l'attributo UITestExtensionPackage per l'assembly.

    [assembly: Microsoft.VisualStudio.TestTools.UITest.Extension.UITestExtensionPackage(
                    "ChartControlExtensionPackage",
                    typeof(ChartControlExtensionPackage.ChartControlExtensionPackage))]
    namespace ChartControlExtensionPackage
    {
       …
    
  9. Nella classe del pacchetto di estensione, eseguire l'override di UITestExtensionPackage.GetService per restituire la classe del provider di proprietà quando un provider di proprietà è obbligatorio.

    internal class ChartControlExtensionPackage : UITestExtensionPackage
    {
        public override object GetService(Type serviceType)
        {
            if (serviceType == typeof(UITestPropertyProvider))
            {
                if (propertyProvider == null)
                {
                    propertyProvider = new ChartControlPropertyProvider();
                }
                return propertyProvider;
            }
            return null;
        }
    
        private UITestPropertyProvider propertyProvider = null;
    }
    
  10. Eseguire l'override delle proprietà e dei metodi astratti rimanenti UITestExtensionPackage.

    public override void Dispose() { }
    
    public override string PackageDescription
    {
        get { return "Supports coded UI testing of ChartControl"; }
    }
    
    public override string PackageName
    {
        get { return "ChartControl Test Extension"; }
    }
    
    public override string PackageVendor
    {
        get { return "Microsoft (sample)"; }
    }
    
    public override Version PackageVersion
    {
        get { return new Version(1, 0); }
    }
    
    public override Version VSVersion
    {
        get { return new Version(10, 0); }
    }
    
  11. Compilare i file binari e copiarli in %ProgramFiles%\Common\Microsoft Shared\VSTT\10.0\UITestExtensionPackages.

[!NOTA]

Questo pacchetto di estensione viene applicato a qualsiasi controllo che è di tipo "testo".Se si stanno testando più controlli dello stesso tipo, è necessario testarli separatamente e definire quali pacchetti di estensione vengono distribuiti quando si registrano i test.

Supportare la generazione di codice implementando una classe per accedere alle proprietà personalizzate

Quando il generatore di test codificati dell'interfaccia utente genera il codice da una registrazione della sessione, utilizza la classe UITestControl per accedere ai controlli.

UITestControl uIAText = this.UIItemWindow.UIChartControlWindow.UIAText;
Assert.AreEqual(this.AssertMethod3ExpectedValues.UIATextState, uIAText.GetProperty("State").ToString());

Se è stato implementato un provider di proprietà per fornire accesso alle proprietà personalizzate del controllo, è possibile aggiungere una classe specializzata utilizzata per accedere a quelle proprietà in modo da semplificare il codice generato.

ControlLegend uIAText = this.UIItemWindow.UIChartControlWindow.UIAText;
Assert.AreEqual(this.AssertMethod3ExpectedValues.UIATextState, uIAText.State);

Hh552522.collapse_all(it-it,VS.110).gifPer aggiungere una classe specializzata per accedere al controllo

CUIT_CodeGen

  1. Implementare una classe che sia derivata da WinControl e aggiungere il tipo del controllo alla raccolta di proprietà di ricerca nel costruttore.

    public class CurveLegend:WinControl 
    {
       public CurveLegend(UITestControl c) : base(c) 
       {
          // The curve legend control is a “text” type of control
          SearchProperties.Add(
             UITestControl.PropertyNames.ControlType, "Text");
       }
    }
    
  2. Implementare le proprietà personalizzate del controllo come proprietà della classe.

    public virtual string State
    {
        get
        {
            return (string)GetProperty("State");
        }
    }
    
  3. Eseguire l'override del metodo UITestPropertyProvider.GetSpecializedClass del provider di proprietà per restituire il tipo della nuova classe per i controlli figlio della curve legend.

    public override Type GetSpecializedClass(UITestControl uiTestControl) 
    { 
       if (uiTestControl.ControlType.NameEquals("Text")) 
       { 
          // This is text type of control. For my control,
          // that means it’s a curve legend control.
          return typeof(CurveLegend); 
       } 
    
       // this is not a curve legend control
       return null;
    }
    
  4. Eseguire l'override del metodo GetPropertyNamesClassType del provider di proprietà per restituire il tipo del metodo della nuova classe PropertyNames.

    public override Type GetPropertyNamesClassType(UITestControl uiTestControl)
    {
        if (uiTestControl.ControlType.NameEquals("Text"))
        {
          // This is text type of control. For my control,
          // that means it’s a curve legend control.
            return typeof(CurveLegend.PropertyNames);
        }
    
        // this is not a curve legend control
        return null;
    }
    

Supportare le azioni Intent-Aware implementando un Filtro Azione

Quando Visual Studio registra un test, acquisisce ogni evento di mouse e tastiera.Tuttavia, in alcuni casi, lo scopo dell'azione può perdersi nella serie di eventi di mouse e tastiera.Ad esempio, se il controllo supporta il completamento automatico, lo stesso insieme di eventi di mouse e tastiera può comportare un valore diverso quando il test viene riprodotto in un ambiente diverso.È possibile aggiungere un plug-in del filtro azione che sostituisce la serie di eventi di mouse e tastiera con una sola azione.In questo modo, è possibile sostituire la sequenza di eventi di mouse e tastiera derivanti dalla selezione di un valore con una sola azione che imposta il valore.Questa operazione consente di proteggere i test codificati dell'interfaccia utente dalle differenze nel completamento automatico da un ambiente a un altro.

Hh552522.collapse_all(it-it,VS.110).gifPer supportare le azioni intent-aware

CUIT_Actions

  1. Implementare una classe di filtro azione che sia derivata da UITestActionFilter, sostituendo le proprietà ApplyTimeout, Category, Enabled, FilterType, Group e Name.

    internal class MyActionFilter : UITestActionFilter
    {
       // If the user actions we are aggregating exceeds the time allowed,
       // this filter is not applied. (The timeout is configured when the
       // test is run.)
       public override bool ApplyTimeout
       {
          get { return true; }
       }
    
       // Gets the category of this filter. Categories of filters
       // are applied in priority order.
       public override UITestActionFilterCategory Category
       {
          get { return UITestActionFilterCategory.PostSimpleToCompoundActionConversion; }
       }
    
       public override bool Enabled
       {
          get { return true; }
       }
    
    
       public override UITestActionFilterType FilterType
       {
          // This action filter operates on a single action
          get { return UITestActionFilterType.Unary; }
       }
    
       // Gets the name of the group to which this filter belongs.
       // A group can be enabled/disabled using configuration file.
       public override string Group
       {
          get { return "ChartControlActionFilters"; }
       }
    
       // Gets the name of this filter.
       public override string Name
       {
          get { return "Convert Double-Click to Single-Click"; }
       }
    
  2. Eseguire l'override di ProcessRule.In questo esempio si sostituisce un'azione di doppio clic con un'azione di clic singolo.

    public override bool ProcessRule(IUITestActionStack actionStack)
    {
        if (actionStack.Count > 0)
        {
            MouseAction lastAction = actionStack.Peek() as MouseAction;
            if (lastAction != null)
            {
                if (lastAction.UIElement.ControlTypeName.Equals(
                     ControlType.Text.ToString(),
                     StringComparison.OrdinalIgnoreCase))
                {
                    if(lastAction.ActionType == MouseActionType.DoubleClick)
                    {
                        // Convert to single click
                        lastAction.ActionType = MouseActionType.Click;
                    }
                }
            }
        }
        // Do not stop aggregation
        return false;
    }
    
  3. Aggiungere il filtro azione al metodo GetService del pacchetto di estensione.

    public override object GetService(Type serviceType) 
    { 
       if (serviceType == typeof(UITestPropertyProvider)) 
       { 
          if (propertyProvider == null)
          {
             propertyProvider = new PropertyProvider();
          } 
          return propertyProvider;
       } 
       else if (serviceType == typeof(UITestActionFilter)) 
       { 
          if (actionFilter == null)
          {
             actionFilter = new RadGridViewActionFilter();
          }
          return actionFilter; 
       } 
       return null;
    }
    
  4. Compilare i file binari e copiarli in %ProgramFiles%\Common Files\Microsoft Shared\VSTT\10.0\UITestExtensionPackages.

[!NOTA]

Il filtro azione non dipende dall'implementazione di accessibilità o dal provider di proprietà.

Eseguire il debug del provider di proprietà o del filtro azione

Il provider di proprietà e il filtro azione sono distribuiti in un pacchetto di estensione che viene caricato ed eseguito dal generatore di test codificati dell'interfaccia utente in un processo distinto dall'applicazione.

Per eseguire il debug del provider di proprietà o del filtro azione

  1. Compilare la versione di debug del pacchetto di estensione copiare i file .dll e .pdb in %ProgramFiles%\Common Files\Microsoft Shared\VSTT\10.0\UITestExtensionPackages.

  2. Eseguire l'applicazione (non nel debugger).

  3. Eseguire il generatore di test codificati dell'interfaccia utente

    codedUITestBuilder.exe /standalone

  4. Associare il debugger al processo codedUITestBuilder.

  5. Impostare i punti di interruzione nel codice.

  6. Nel generatore di test codificati dell'interfaccia utente, creare le asserzioni per verificare il provider di proprietà, e le azioni di registrazione per verificare il filtro azione.

Risorse esterne

Hh552522.collapse_all(it-it,VS.110).gifLinee guida

Verifica della Continuous Delivery con Visual Studio 2012 – Capitolo 2: Test delle Unità: Test dell'interno

Vedere anche

Riferimenti

AccessibleObject

Concetti

Verifica del codice mediante test codificati dell'interfaccia utente