Introdução
Você certamente já ouviu falar sobre testes de regressão e aceitação. Mas você sabe quanto é realmente gasto em testes de aceitação em um projeto?
Podemos obter uma resposta rapidamente com a ajuda de um sistema de controle de tempo como o TMetric.
Em nosso projeto, testes de aceitação um aplicativo de desktop de cerca de 100 montagens levou mais de 2 pessoas-semanas. Novos especialistas em controle de qualidade que não conheciam bem o aplicativo estavam tendo as maiores dificuldades. Em comparação com especialistas em QA mais experientes, eles gastaram muito mais tempo em cada caso de teste.
No entanto, na minha opinião, a parte mais desagradável foi essa – se algum erro crítico for encontrado antes do lançamento, o teste de aceitação deve ser realizado novamente depois que esses erros são corrigidos.
Os testes de unidade escritos ajudaram um pouco, mas ainda reduziram principalmente o tempo gasto em testes de regressão. Com isso, quando a quantidade de testes manuais atingiu um nível crítico, começamos a caminhar para a automação.
ROI
Antes de escrever testes automatizados de interface do usuário, precisávamos avaliar a lucratividade de nossos investimentos. Fizemos isso com a ajuda do ROI (Return On Investment https://en.wikipedia.org/wiki/Return_on_investment)
Calcular o ROI do teste de UI também se tornou uma tarefa interessante com várias variáveis desconhecidas:
ROI =Lucro / Despesas
ou
ROI =(Lucro – Despesas) / Despesas
Nesta fase, precisávamos de um pequeno protótipo que nos ajudasse a estimar todas as despesas necessárias. Ele mostrou resultados muito peculiares:realizar testes de aceitação leva aproximadamente o mesmo tempo que automatizar esse processo. A princípio, essa informação parecia questionável, mas quando investigamos mais a fundo, os motivos ficaram claros:
- Os novos especialistas em controle de qualidade podem ter uma compreensão limitada das etapas descritas nos casos de teste. Quando isso acontecer, algumas pessoas estarão envolvidas no teste de aceitação para ajudar a entender melhor a situação. Aqui, também devemos ter em mente a questão de quão relevantes são as informações que temos sobre as configurações e requisitos do ambiente.
- Às vezes, as pessoas envolvidas no teste de aceitação passam algum tempo aprendendo a documentação técnica.
- O próprio aplicativo interage com um conjunto específico de serviços. Se um deles não estiver disponível, os especialistas em QA menos experientes gastarão tempo descrevendo bugs que os desenvolvedores, por sua vez, investigarão. Como resultado, o tempo é desperdiçado porque o serviço necessário simplesmente não foi executado corretamente após um blecaute/atualização de hardware/reinicialização do computador.
- Os computadores dos testadores de controle de qualidade não são muito poderosos. Se não houver SSD, você já notará durante a instalação. Além disso, se o aplicativo estiver trabalhando com carga pesada, é possível que um arquivo de paginação lento seja usado.
- Para ser honesto, nos empolgamos e esquecemos que estamos trabalhando com automação. A propósito, você fechou a guia Youtube no seu navegador?
Agora, vamos voltar ao ROI. Para simplificar as coisas, os cálculos foram realizados por tempo. Vamos calcular o lucro como economia em testes manuais, e o período de tempo que veremos é de um ano:
Lucro =(X – Y) * N =(60 – 1) * 8 =472 dias
X – tempo gasto em testes manuais (60 dias)
Y – tempo gasto em testes automatizados (1 dia)
N – a quantidade de tempo que a aceitação foi realizada
A seguir, veremos as despesas:
Despesas =A + B + C + D + E + F =0 + 10 + 5 + 50 + 7 + 8 =80
A – O custo da licença da ferramenta de automação. No nosso caso, foi utilizada uma ferramenta gratuita.
B – Treinamento de um especialista em QA (10 dias)
C – Preparação da infraestrutura (5 dias)
D – Desenvolvimento de testes (50 dias)
E – Execução de testes e descrição de bugs descobertos no processo (7 dias)
F – Manutenção de testes (8 dias)
Total:
ROI =Lucro / Despesas =472 / 80 =5,9
Claro, alguns dos aspectos aqui são estimados. Para avaliar nossos próprios cálculos, passamos algum tempo investigando os recursos oferecidos por soluções pagas e várias calculadoras de ROI. Com isso, calculamos o valor médio de ROI de 2 ou 3, o que é um ótimo resultado.
Estruturas existentes
Tendo examinado as questões organizacionais, vamos nos concentrar nas questões do tipo técnico. O mais importante deles foi escolher um framework para automatizar os testes de nosso aplicativo de desktop. Tínhamos os seguintes requisitos com base nas características do nosso projeto:
- Os testes serão desenvolvidos e executados em máquinas Windows
- A estrutura deve ser adaptada para testar aplicativos de desktop
- Os testes de interface do usuário podem ser integrados ao processo de CI. Já estávamos usando Jenkins, então era preferível aqui
- A capacidade de escrever testes em um IDE amigável – ele precisa ter realce de sintaxe, navegação de script de teste e conclusão de código no estilo IntelliSense
- Despesas mínimas com treinamento de controle de qualidade. Por alguns motivos, nossos especialistas em controle de qualidade não quiseram escrever testes no Brainfuck
- É preferível uma comunidade no Stack Overflow, MSDN etc.
Teste concluído
Esta plataforma inicialmente nos atraiu por sua maturidade, o que deu esperanças em relação aos aspectos técnicos.
A primeira coisa que encontramos foi um IDE instável e bastante obsoleto. O ambiente tratou o destaque de sintaxe de forma mais ou menos decente, mas houve problemas significativos com navegação (Ir para definição), pesquisa e preenchimento automático de código:essa funcionalidade não funcionou aproximadamente 60% das vezes. O gravador embutido e um analógico Inspect funcionaram bem. No final, o IDE nos deu uma surpresa desagradável quando começou a passar argumentos para o aplicativo. Isso, como esperado, causou erros no desempenho do aplicativo:
--no-sandbox program files (x86)\smartbear\testcomplete12\x64\bin\Extensions\tcCrExtension\tcCEFHost.dll;application/x-testcomplete12-0-chrome-browser-agent
Nesta fase, envolvemos o suporte da TestComplete na situação para tentar economizar tempo e avaliar a qualidade do suporte técnico antes de comprar uma licença. Após algumas cartas enviadas ao suporte técnico, obtivemos uma resposta – devemos ignorar os argumentos passados para o aplicativo. Estranho, não é? Investigando mais a fundo, descobrimos que esses argumentos são necessários para testar aplicativos que usam CEF. Em nossa carta seguinte, afirmamos que usamos a CEF, e fomos orientados pelos especialistas de suporte a não ignorar os argumentos. Quando perguntamos como exatamente usá-los, a resposta voltou para “Ignore os argumentos”.
Deixando nossa conversa com o suporte técnico, voltamos para a documentação do IDE (sem muita esperança). Tinha mais informações, mas não encontramos nada referente ao caso em questão. Além disso, de acordo com esta mesma documentação, o IDE deveria ter se comportado de forma diferente desde o início.
Supõe-se que os testes em TestComplete serão escritos usando VBScript.
Se você olhar por tempo suficiente, você pode ouvir isso. A Microsoft sugere converter essa “maravilha” em scripts do PowerShell. Como alternativa, JavaScript e Python podem ser usados, o que ajuda na situação.
Como uma ferramenta gratuita, o TestComplete seria suportável, mas o site deles tem uma página de preços e os preços são por usuário. Como resultado, é isso que obteremos após a compra da ferramenta:
- IDE que você deseja fechar
- Compatibilidade com scripts de 1996
- Um gravador para não escrever tudo manualmente
- Outra inspeção, mas com sinos e assobios
- 2 tipos de respostas de suporte técnico
- Documentação que não representa a realidade
Pior acordo comercial de todos os tempos, vamos seguir em frente.
IU codificada
Retirada tática, reagrupamento, e flanqueamos a questão. Por um lado, aprendemos a usar o Visual Studio como um IDE. Por outro lado, nossa abordagem foi baseada nos componentes de interface do usuário do DevExpress que estamos usando. Como resultado, encontramos algumas informações interessantes sobre o framework Coded UI que é usado oficialmente no DevExpress para automatizar o teste de UI. Esse framework está tão integrado ao processo de teste interno que existe até uma extensão do Visual Studio para ele.
Havia uma comunidade extensa, a Microsoft promoveu a ferramenta em seu site, e este produto também foi mencionado no “Microsoft Visual Studio”. Para encurtar a história, tudo parecia promissor e começamos a preparar o framework.
O primeiro requisito que encontramos foi o Visual Studio Enterprise. Além disso, esta versão do Visual Studio era necessária não apenas para escrever testes, mas também para executá-los. Isso significa que o mstest através do qual a inicialização será executada no caso de CI também deve fazer parte da edição Enterprise.
Todas as ferramentas de interface do usuário codificadas necessárias podem ser instaladas ativando as caixas de seleção correspondentes quando o VS é instalado ou modificado.
A abordagem para escrever testes foi bastante agradável:comandos integrados ao shell permitiram lançar rapidamente um gravador que gera um teste de unidade e uma classe “mapa” descrevendo a interface do usuário. Ferramentas adicionais integradas ao VS possibilitaram a criação de classes de teste separadas sem chamar o código.
A única peculiaridade que notamos foi uma classe parcial que continha a descrição do controle e era dividida em duas partes. Junto com muitas outras coisas, está descrito na documentação. Esta documentação é suficiente para um processo de trabalho confortável:exemplos de código e capturas de tela tornam todas as informações técnicas prontamente acessíveis e fáceis de entender. Para simplificar, quando o gravador descreve a interface do usuário, um arquivo “Designer.cs” é gerado. Este arquivo é responsável por reutilizar o código que descreve a interface do usuário. Tudo o que o gravador não pode manipular deve ser escrito manualmente e salvo em algum lugar fora da parte gerada automaticamente pela classe. Isso é muito semelhante às classes parciais escritas por designers de VS ao criar controles. A prioridade das operações executadas nos controles e de suas verificações de estado é descrita em um método ao qual o gravador adiciona um atributo TestMethod padrão.
As nuvens começaram a se acumular sobre a estrutura quando começamos a examinar as coisas que o gravador gerava . Em primeiro lugar, ele obscureceu alguns dos problemas do aplicativo:a propriedade Name de alguns controles não foi especificada e o gravador considerou aceitável essa instância ridícula de violação de regra e pesquisou controles no texto. Além disso, ele lidava com controles complexos de forma muito ineficiente. Por exemplo, os nós TreeView foram pesquisados por índice de nós, o que tornou a classe “mapa” criada inutilizável no caso de expansão da interface. E o valor do gravador caiu significativamente aos nossos olhos – qual é o sentido de gerar automaticamente o código se você precisar verificá-lo depois?
Poderíamos fazer as pazes com todas essas coisas e encontrar uma solução louvável, mas de repente, o trovão atingiu:Microsoft afirmou que esta tecnologia é agora obsoleta. Com isso, o VS 2019 se tornou a última versão do Visual Studio compatível com a IU codificada. A possibilidade de depender do VS 2019 agora e com alguns anos de antecedência não parecia tão assustadora, mas nosso projeto é bastante grande, então as dificuldades podem começar em algum lugar (2025, por exemplo).
Vamos resumir. Com a IU codificada, teremos:
- Um poderoso IDE pago
- Toda infraestrutura já criada para testes:tanto do lado do IDE quanto do nosso CI
- A capacidade de pedir ajuda a qualquer desenvolvedor do nosso projeto porque estamos escrevendo testes em C# no mesmo IDE
- Uma grande quantidade de documentação de boa qualidade
- Alguns tristes especialistas em controle de qualidade que colocaram seu código na parte gerada automaticamente da classe e o perderam durante o processo de geração automática
- Muito código gerado que funciona e que você precisa submeter a uma revisão rigorosa
- Uma abordagem escandalosamente transparente para CI:você pode escrever código para iniciar testes por meio do mstest com os olhos fechados
- Uma gigante vermelha da automação que morre lentamente, que cresce constantemente a partir de novos testes e está perigosamente perto de se transformar em uma anã branca desbotada representada por uma máquina absolutamente isolada com software irreversivelmente obsoleto ou em uma explosão de supernova quando o projeto implode sob o pressão de novas atualizações.
Tudo parecia bom, exceto pelo último ponto. É por isso que precisávamos continuar nossa busca.
TestStack.Branco
Estávamos trabalhando em testes de prototipagem com a ajuda de White em paralelo para investigar a funcionalidade da Coded UI.
White em si é um wrap em torno das bibliotecas 'Microsoft.Automation' que pareciam muito promissoras, e White também é semelhante a Coded IU. No entanto, em um exame mais detalhado, descobrimos que é muito mais austero, e você pode notá-lo em todos os lugares - desde o fato de não haver gravador até a estrutura de teste real. Por exemplo, executar o aplicativo, procurar uma janela e pressionar o botão “Executar” fica assim:
var appPath = @"C:\Program files\UiAutomatedTestApplication\TestApplication.exe"; var app = TestStack.White.Application.Launch(appPath); var windowSearchCriteria = SearchCriteria.ByAutomationId("MainForm"); var window = app.GetWindow(windowSearchCriteria, InitializeOption.NoCache); var execute = window.GetElement(SearchCriteria.ByText("Execute")); var invokePattern = (InvokePattern)execute.GetCurrentPattern(InvokePattern.Pattern); invokePattern.Invoke(); app.WaitWhileBusy();
Mesmo que não haja reclamações na hora de rodar a aplicação, a necessidade de trabalhar com a classe InvokePattern é muito questionável. A classe InitializeOption também parece estranha porque tem acesso ao membro estático WithCache, mas deve ser usada estritamente internamente:
public class InitializeOption { // // Summary: // This option should not be used as this is only for internal white purposes public static InitializeOption WithCache { get; } public static InitializeOption NoCache { get; } public virtual bool Cached { get; } public virtual string Identifier { get; } public virtual bool NoIdentification { get; } // // Summary: // Specify the unique identification for your window. White remembers the location // of UIItems inside a window as you find them. Next time when items inside the // same window is found they are located first based on position which is faster. // // Parameters: // identifier: public virtual InitializeOption AndIdentifiedBy(string identifier); public virtual void NonCached(); public override string ToString(); }
Decisões estranhas como essa estão por toda parte, e a estrutura se mostra muito abstrata para o controle de qualidade.
A documentação é de boa qualidade e deixou uma boa impressão geral. O código-fonte do projeto estava hospedado no github, mas o último commit foi datado de 8 de janeiro de 2016.
Resumindo as informações sobre White, teríamos:
- Documentação decente
- Acesso ao código-fonte
- Uma pequena comunidade
- A necessidade de explicar a todos os especialistas de controle de qualidade que o comportamento do controle é implementado por meio da classe Pattern
- Um repositório antigo do qual definitivamente precisaríamos fazer um fork
A parte mais desagradável foi a necessidade de desenvolver nosso próprio framework, que gostaríamos de evitar. Então tivemos que seguir em frente.
Ápio
Já encontramos Appium em nossa busca antes, mas só começamos a considerá-lo seriamente depois que a Microsoft parou de usar Coded UI.
À primeira vista, testar com a ajuda do Appium parece um caça-níqueis com três cilindros. A primeira mostra o idioma para o qual existe uma API que permite a interação com o motorista. Isso fornece a capacidade de escrever testes em qualquer linguagem familiar:Python, C#, Java etc. O segundo rolo mostra o aplicativo de driver que serve como uma camada intermediária entre os testes e o produto que estamos testando. Conforme descrito na documentação, a interação com os testes é realizada usando o JSON Wire Protocol – isso é o que realmente nos dá a capacidade de escrever testes em qualquer linguagem. E o terceiro rolo mostra o objeto que estamos testando. Não importa se é um site, um aplicativo móvel ou um aplicativo de desktop, desde que o driver correspondente esteja em execução. Como você pode ver, os componentes são elegantemente intercambiáveis .
A estimativa da relevância do pacote foi satisfatória – na página do Github, pudemos ver que o repositório tinha novos commits. Ao examinar o repositório WinAppDriver, descobrimos que havia até um gravador nele.
Começamos a perceber alguns problemas enquanto escrevíamos um protótipo. Por exemplo, como a estrutura é muito multifuncional, o WindowsElement responsável pelo controle da área de trabalho possui um método FindElementByCssSelector que gera a seguinte exceção na execução:“Erro inesperado. Comando não implementado:estratégia de localizador de seletor css não é suportada”. No próximo artigo, falaremos sobre os problemas que encontramos ao trabalhar com esse framework com mais detalhes, mas por enquanto gostaria de dizer que conseguimos lidar com todos eles.
Como resumo, aqui está o que teremos ao usar o Appium:
- A capacidade de testar a funcionalidade do aplicativo que requer interação com um navegador (abertura da página de feedback, ativação on-line, verificação de entrega de e-mail) no escopo de uma infraestrutura e um teste
- A capacidade de trabalhar com qualquer edição do Visual Studio
- A capacidade de testar um aplicativo de desktop que usa um navegador para renderizar a interface do usuário. Um bom exemplo disso seria o Azure Data Studio
- Todas as vantagens que temos com a IU codificada
- Uma estrutura gratuita que a Microsoft recomenda usar
- Infraestrutura familiar aos especialistas de controle de qualidade que trabalharam com o Selenium
- Um repositório atualizado com novos commits
- Uma comunidade decentemente grande que, no entanto, não é tão grande quanto a comunidade da IU codificada
- Um gravador com funcionalidade limitada
- A necessidade de executar um aplicativo de driver para teste. Não é muito conveniente, mas tem sua própria funcionalidade de registro
- Muitas oportunidades para dar um tiro no pé devido à infeliz herança do WindowsElement do AppiumWebElement
Passando por todos os pontos com requisitos para frameworks e comparando todos os problemas encontrados em cada um desses frameworks, finalmente escolhemos o Appium.
Conclusão
Foi interessante trabalhar com todos esses frameworks porque cada um deles era baseado em uma filosofia única de abordagem de testes automatizados. Parte deles apenas começou seu caminho enquanto outros estavam chegando ao eclipse ou já desapareceram. Você pode evitar se perder nas muitas soluções disponíveis criando uma lista de requisitos específicos para a ferramenta e tendo uma equipe responsável com interação bem estabelecida entre seus membros. E não se esqueça de que os testes futuros são tanto um projeto quanto o código usual, com backlog, placas, CI, refatoração e tudo mais.