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:
Suporte a registro e reprodução e validação de propriedade com a implementação de acessibilidade
Adicionar validação de propriedade personalizada, Implementando um provedor de propriedade
Suporte a ações intencionais implementando um filtro de ação
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.
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.
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.
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; } } }
Substituir o objeto acessível Role, State, GetChild e GetChildCount propriedades e métodos.
Implementar outro objeto de acessibilidade para o controle filho e substituir o controle filho AccessibilityObject propriedade para retornar esse objeto de acessibilidade.
Substituir o Bounds, Name, Parent, Role, State, Navigate, e Select propriedades e métodos para o objeto de acessibilidade do controle filho.
Observaçã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.
Para oferecer suporte à validação de propriedade personalizada
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(); } } }
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.
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 { } }
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(); }
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; }
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(); }
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 { } }
Definir o UITestExtensionPackage atributo do assembly.
[assembly: Microsoft.VisualStudio.TestTools.UITest.Extension.UITestExtensionPackage( "ChartControlExtensionPackage", typeof(ChartControlExtensionPackage.ChartControlExtensionPackage))] namespace ChartControlExtensionPackage { …
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; }
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); } }
Criar os binários e copiá-los para % ProgramFiles %\Common Files\Microsoft Shared\VSTT\10.0\UITestExtensionPackages.
Observaçã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
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"); } }
Implemente as propriedades personalizadas do controle como propriedades da classe.
public virtual string State { get { return (string)GetProperty("State"); } }
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; }
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
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"; } }
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; }
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; }
Criar os binários e copiá-los para % ProgramFiles %\Common Files\Microsoft Shared\VSTT\10.0\UITestExtensionPackages.
Observaçã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
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.
Execute o aplicativo (não no depurador).
Execute o teste de IU codificado.
codedUITestBuilder.exe /standalone
Anexe o depurador ao processo codedUITestBuilder.
Definir pontos de interrupção em seu código.
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.