Compartilhar via


Habilitar testes de IU codificado dos controles

O controle pode ser testado mais fácil se você implementar o suporte para a estrutura de testes de UI codificada.Você pode adicionar incrementalmente níveis crescentes de suporte.Você pode iniciar, oferecendo suporte a validação de registro e a reprodução e a propriedade.Você pode criar para permitir que o construtor de teste de IU codificado reconhecer as propriedades personalizadas do controle e fornecem classes personalizadas para acessar as propriedades do código gerado.Você também pode ajudar as codificados teste construtor captura ações de IU de maneira mais próxima a intenção da ação que está sendo registrada.

Neste tópico:

  1. Suporte a registro e reprodução e validação de propriedade com a implementação de acessibilidade

  2. Adicionar validação de propriedade personalizada, Implementando um provedor de propriedade

  3. Oferecer suporte à geração de código ao implementar uma classe para propriedades personalizadas de acesso

  4. Suporte a ações intencionais implementando um filtro de ação

CUIT_Full

Suporte a registro e reprodução e validação de propriedade com a implementação de acessibilidade

O teste de IU codificado captura informações sobre os controles que ele encontra durante uma gravação e, em seguida, gera código para repetir essa sessão.Se o controle não dá suporte a acessibilidade, o teste de IU codificado capturará ações (como cliques de mouse) usando coordenadas da tela.Quando o teste é reproduzido, o código gerado emitirá os cliques do mouse nas mesmas coordenadas de tela.Se o controle é exibido em um local diferente na tela quando o teste é reproduzido, o código gerado falhará executar essa ação em seu controle.Isso pode resultar em falhas se o teste é reproduzido em configurações de tela diferente, em ambientes diferentes, ou depois que houve alterações no layout da interface do usuário.

CUIT_RecordNoSupport

Se você implementar a acessibilidade, no entanto, o teste de IU codificado usará que para capturar informações sobre o controle quando ele registra um teste e gera o código.Em seguida, quando você executa o teste, o código gerado repetirá esses eventos em relação a seu controle, mesmo que esteja em outro lugar na interface do usuário.Os autores de teste também será capazes de criar declarações usando as propriedades básicas de seu controle.

CUIT_Record

Para dar suporte a registro e reprodução, validação de propriedade e navegação do controle do Windows forms

Implementar a acessibilidade para o controle conforme descrito no procedimento a seguir e explicados em detalhes em AccessibleObject.

CUIT_Accessible

  1. Implementar uma classe que deriva de ControlAccessibleObjecte substitua o AccessibilityObject propriedade para retornar um objeto de sua 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. Substituir o objeto acessível Role, State, GetChild e GetChildCount propriedades e métodos.

  3. Implementar outro objeto de acessibilidade para o controle filho e substituir o controle filho AccessibilityObject propriedade para retornar esse objeto de acessibilidade.

  4. Substituir o Bounds, Name, Parent, Role, State, Navigate, e Select propriedades e métodos para o objeto de acessibilidade do controle filho.

ObservaçãoObservação

Este tópico é iniciado com o exemplo de acessibilidade em AccessibleObject neste procedimento e, em seguida, baseia-se no que nos procedimentos restantes.Se você quiser criar uma versão de trabalho do exemplo de acessibilidade, crie um aplicativo de console e, em seguida, substitua o código em Program.cs com o código de exemplo.Você precisará adicionar referências a acessibilidade, System. Drawing e System.Windows.Forms.Você deve alterar o inserir tipos Interop para acessibilidade como False eliminar um aviso de compilação.Você pode alterar o tipo de saída do projeto do aplicativo de Console para o aplicativo do Windows para que uma janela de console não aparece quando você executar o aplicativo.

Suporte a validação de propriedade personalizada, Implementando um provedor de propriedade

Depois que você implementou o suporte básico para a validação do registro e a reprodução e a propriedade, você pode disponibilizar propriedades personalizadas do controle para testes de UI codificados implementando um UITestPropertyProvider plug-in.Por exemplo, o procedimento a seguir cria um provedor de propriedade que permite que os testes de UI codificados acessar a propriedade State de controles de filho CurveLegend do controle de gráfico.

CUIT_CustomProps

Para oferecer suporte à validação de propriedade personalizada

CUIT_Props

  1. Substituir curva legenda acessível do objeto Description separados de propriedade para passar valores de propriedade avançada na cadeia de caracteres de descrição, a descrição principal (e entre si se você estiver implementando várias propriedades) por ponto e vírgula (;).

    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. Criar um pacote de extensão de teste da interface do usuário para o seu controle, criando um projeto de biblioteca de classes e adicione referências a acessibilidade, Microsoft.VisualStudio.TestTools.UITesting, Microsoft.VisualStudio.TestTools.UITest.Common e Microsoft.VisualStudio.TestTools.Extension.Alterar o inserir tipos de interoperabilidade para acessibilidade como False.

  3. Adicionar uma classe de provedor de propriedade que é derivada de 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. Implementar o provedor de propriedade colocando nomes de propriedade e descritores de propriedade em uma Dictionary.

    // 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. Substituir UITestPropertyProvider.GetControlSupportLevel para indicar que seu assembly fornece suporte de controle específicos para o controle e seus filhos.

    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. Substituir os métodos abstratos restantes de 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. Adicionar uma classe de pacote de extensão que é derivada de 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. Definir o UITestExtensionPackage atributo do assembly.

    [assembly: Microsoft.VisualStudio.TestTools.UITest.Extension.UITestExtensionPackage(
                    "ChartControlExtensionPackage",
                    typeof(ChartControlExtensionPackage.ChartControlExtensionPackage))]
    namespace ChartControlExtensionPackage
    {
       …
    
  9. Na classe de pacote de extensão, substitua UITestExtensionPackage.GetService para retornar a classe do provedor de propriedade quando um provedor de propriedade é solicitado.

    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. Substituir os métodos abstratos restantes e propriedades de 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. Criar os binários e copiá-los para % ProgramFiles %\Common Files\Microsoft Shared\VSTT\10.0\UITestExtensionPackages.

ObservaçãoObservação

Este pacote de extensão será aplicado a qualquer controle que é do tipo "Text".Se você estiver testando vários controles do mesmo tipo, você precisará testá-los separadamente e gerenciar quais pacotes de extensão são implantadas quando você grava os testes.

Oferecer suporte à geração de código ao implementar uma classe para propriedades personalizadas de acesso

Quando o teste de IU codificado gera o código de uma gravação da sessão, ele usa o UITestControl classe para acessar os controles.

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

Se você já implementou um provedor de propriedade para fornecer acesso a propriedades personalizadas do controle, você pode adicionar uma classe especializada que é usada para acessar essas propriedades para que o código gerado é simplificado.

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

Para adicionar uma classe especializada para o controle de acesso

CUIT_CodeGen

  1. Implementar uma classe que é derivada de WinControl e adicione o tipo do controle à coleção de propriedades de pesquisa no construtor.

    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. Implemente as propriedades personalizadas do controle como propriedades da classe.

    public virtual string State
    {
        get
        {
            return (string)GetProperty("State");
        }
    }
    
  3. Substituir o provedor de propriedade UITestPropertyProvider.GetSpecializedClass método para retornar o tipo da nova classe da curva controles filho de legenda.

    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. Substituir o provedor de propriedade GetPropertyNamesClassType método para retornar o tipo de método de PropertyNames a nova classe.

    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;
    }
    

Suporte a ações intencionais implementando um filtro de ação

Quando o Visual Studio registra um teste, ele captura de cada evento de mouse e teclado.No entanto, em alguns casos, pode ser perdida a intenção da ação de uma série de eventos de mouse e teclado.Por exemplo, se o controle suporta preenchimento automático, o mesmo conjunto de eventos de mouse e teclado pode resultar em um valor diferente quando o teste é reproduzido em um ambiente diferente.Você pode adicionar um filtro de ação plug-in que substitui a série de eventos de teclado e mouse com uma única ação.Dessa forma, você pode substituir a série de eventos de mouse e teclado, resultando na seleção de um valor com uma única ação que define o valor.Isso protege os testes de UI codificados contra as diferenças em preenchimento automático de um ambiente para outro.

Para dar suporte a ações intencionais

CUIT_Actions

  1. Implementar uma classe de filtro de ação que é derivada de UITestActionFilter, substituindo as propriedades 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. Substituir ProcessRule.O exemplo aqui realpces uma ação de clique duplo com um único clique em ação.

    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. Adicionar o filtro de ação para o GetService método do seu pacote de extensão.

    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. Criar os binários e copiá-los para % ProgramFiles %\Common Files\Microsoft Shared\VSTT\10.0\UITestExtensionPackages.

ObservaçãoObservação

O filtro de ação não dependem da implementação de acessibilidade ou no provedor de propriedade.

Depurar seu provedor de propriedade ou filtro de ação

O filtro de provedor e a ação de propriedade são implementados em um pacote de extensão que é carregado e executado pelo construtor de teste UI codificado em um processo separado do seu aplicativo.

Para depurar seu filtro de ação ou provedor de propriedade

  1. Criar a versão de depuração da sua cópia do pacote de extensão de arquivos. dll e. PDB para % ProgramFiles %\Common Files\Microsoft Shared\VSTT\10.0\UITestExtensionPackages.

  2. Execute o aplicativo (não no depurador).

  3. Execute o teste de IU codificado.

    codedUITestBuilder.exe /standalone

  4. Anexe o depurador ao processo codedUITestBuilder.

  5. Definir pontos de interrupção em seu código.

  6. No construtor de teste de IU codificado, criar declarações para exercitar seu provedor de propriedade e gravar ações para experimentar os filtros de ação.

Recursos externos

Orientação

Teste para entrega contínua com Visual Studio 2012 – Capítulo 2: Unit Testing: Testing the Inside (Teste de Unidade: Teste no Interior)

Consulte também

Referência

AccessibleObject

Conceitos

Verificando código pela Automação da Interface do Usuário