Regressão testando uma interface complexa
Cada recurso adicionado ao mix aumenta a chance de um novo bug aparecer, uma promessa que geralmente é cumprida. Ao desenvolver um aplicativo Web grande e complexo, precisamos poder verificar continuamente as regressões e verificar se tudo o que funcionou até agora ainda está funcionando. Para que pelo menos não quebremos mais do que precisamos. Avance Network é uma empresa da web e deve entregar em um ritmo muito rápido. Nós enviamos muitos recursos continuamente. Sob tais circunstâncias, não importa quão grande seja sua equipe de controle de qualidade, ela nunca conseguirá cobrir todo o sistema para cada recurso entregue.
Isso significa que uma estrutura abrangente de automação de testes é uma obrigação.
Entrando em prova: Selênio
O Selenium é uma estrutura robusta de automação de navegador, permitindo escrever testes na web com muitas linguagens diferentes: Java, C #, PHP, Python, etc. Simplesmente dito: ele fornece uma API que permite simular o comportamento do usuário nos navegadores. O Selenium suporta todos os principais navegadores e fornece uma API relativamente simples para testar tudo a interface do usuário.
Uma espiada em um formulário nos bastidores
Os bastidores cresceram com o tempo. Os recursos são continuamente desenvolvidos e implantados a cada semana, muitos deles por equipes diferentes, que podem inadvertidamente quebrar as funcionalidades uns dos outros. A cada mudança, precisamos garantir que não quebramos nada. Mesmo com as equipes de controle de qualidade trabalhando 24 horas, precisamos ter a melhor cobertura possível. Às vezes, uma pequena correção em um relatório pode causar estragos em um formulário diferente, e precisamos entender isso a tempo. Então, como podemos testar esse gigante de um aplicativo?
Para cobrir o máximo possível, usamos diferentes estruturas de teste:
- Mockito para testes de unidade de servidor
- Karma para testes de unidade JS
- Wraith para teste visual (comparação de captura de tela)
- Selênio para testes funcionais e de aceitação do cliente
- Garantia de REST para teste de API
Nós nos esforçamos para cobrir cada fluxo possível que possa ocorrer com a interação do usuário com o Selenium. O teste dos fluxos se torna parte do teste do servidor, pois valida todos os pontos de integração. Como é quase impossível cobrir tudo, cobrimos a maioria dos casos de uso relevantes. A cobertura de teste é aumentada ao longo do tempo com estas regras:
- Como parte da correção de cada bug, um desenvolvedor precisa adicionar um teste de cobertura para verificar se o mesmo bug não retornará
- Como parte do desenvolvimento de um novo recurso, um desenvolvedor precisa adicionar testes que cubram o novo comportamento. O recurso é aprovado para produção somente após o controle de qualidade manual e todos os testes de selênio terem passado
Com o tempo, isso nos ajudou a criar uma cobertura densa do aplicativo Backstage.
Solução de Selênio do Avance Network
Vamos examinar as diferentes partes.
A estrutura do WebDriver
Para poder adicionar testes facilmente, criamos uma estrutura que representa as páginas reais do aplicativo. Cada elemento é representado por um componente Selenium, permitindo que os testes interajam com o site em nossos testes, como se fôssemos um usuário.
Para o Selenium poder simular o comportamento do usuário, precisamos criar uma representação de todos os componentes no site. Cada elemento é representado por um componente Selenium, permitindo que os testes naveguem e interajam com a interface do usuário. Nós chamamos isso de WebDriver Framework.
Componentes da aplicação
Para cada tipo de componente da web, criamos uma representação do Selenium que sabe como reagir e ler os dados desse componente.
Ele recebe o objeto WebElement Selenium que o identificou na página da web e o usa como base para todos os comportamentos.
Por exemplo, um componente da caixa de seleção:
O construtor Checkbox 'recebe o WebElement que agrupa o elemento real. Por exemplo, se uma caixa de seleção puder ser localizada por seu ID, ela pode ser passada assim:
1 2 3 4 | @FindBy(id=”myCheckboxId”) private WebElement myCheckboxElement; …. Checkbox myCheckbox = new Checkbox(myCheckboxElement); |
Os componentes reais são combinados na seção de estrutura do aplicativo.
Estrutura
Depois de termos todos os componentes necessários, os reunimos nas diferentes páginas da web em nosso aplicativo. Uma classe Page representa uma única página da Web, e suas diferentes implementações nos permitem representar todas as páginas que temos e suas relações.
Escrevendo os testes
A solução Selenium do Avance Network é fornecida pela JUnit, fornecendo o poder de asserções e desenvolvimento focado em testes.
A sua estrutura é em JUnit forma, com @Before anotação para a preparação teste, @After para teste da lágrima de cima, e @Test para os diferentes testes.
Dividimos os testes em classes, de acordo com a seção que eles cobrem no Backstage. Este é um exemplo de estrutura de pacote para nossos testes:
- Campanhas - Todos os testes relacionados à campanha
- Gerenciamento - todos os testes relacionados ao gerenciamento de campanhas
- Formulário - Todos os testes relacionados à criação / edição de campanhas
- Criar - todos os testes de criação de campanha
- Editar - todos os testes de edição de campanha
- Validar - Todos os testes de validação (bem-sucedidos e erros)
- Diversos
- Criar - todos os testes de criação de campanha
- Inventário - todos os testes relacionados ao inventário da campanha
- Tabela - Todos os testes de relatório da tabela de gerenciamento de campanhas
- Formulário - Todos os testes relacionados à criação / edição de campanhas
- Relatórios - Outros testes de relatório de campanha
- RSS - Testes de inventários de RSS
- SelfService - Testes de fluxo de autoatendimento - aprovando e rejeitando campanhas
- Gerenciamento - todos os testes relacionados ao gerenciamento de campanhas
- Ferramentas editoriais
- BlockContent
- LookBackSettings
- BlockContent
- …..
Cada pacote possui uma classe base que é estendida por todas as classes em subpacotes. Essas classes base fornecem toda a lógica necessária para gerar entidades relacionadas a esta seção.
Para evitar um tempo de espera super longo para a conclusão dos testes, muita reflexão foi colocada nas etapas de preparação do teste (os métodos @Before e @BeforeClass). Como testes semelhantes são reunidos nas mesmas classes, um método de preparação BeforeClass gera todas as entidades necessárias que podem ser reutilizadas. Enquanto o método Before cuida da criação que não pode ser compartilhada (fazendo login, acessando a página etc.). Para facilitar a geração fácil de entidades, criamos uma classe de utilitário, DatabaseUtils, usada para todas as etapas de preparação.
Dicas para escrever testes de selênio
Depois de muita dor e ganho, gostaria de compartilhar alguns pontos importantes a serem observados ao escrever os testes de selênio.
- Copiar / colar é seu inimigo. Como muitos testes podem repetir os mesmos fluxos com pequenas alterações, identifique todos os fluxos semelhantes e agrupe-os em funções utilitárias. O código de teste pode se tornar muito grande muito rápido e, se você não prestar atenção, a manutenção pode se tornar uma tarefa impossível.
- Não use as mesmas entidades e dados para testes diferentes; se eles estiverem sendo modificados durante os testes, os testes serão executados em paralelo e poderão interromper os dados uns dos outros. Gere apenas entidades que permanecerão imutáveis nos métodos BeforeClass.
- Você não precisa testar tudo . Para o comportamento de componentes ou elementos de páginas pequenas, você pode usar testes de Karma. Os testes de selênio são lentos - use-os para fluxos de usuários e não para todos os aspectos dos componentes.
- Dito isto - afirme tudo o que é possível. Enquanto a interação é lenta, a afirmação é rápida. Afirmar a existência de elementos, sua visibilidade, seus estados - o que vier à mente.
- Lembre-se de que os testes levam tempo para serem executados porque emulam o comportamento do usuário. Aspire para gerar fluxos enxutos e específicos, com a maioria das compilações feitas no banco de dados e não através do próprio teste.
- Não entre em pânico! Não é específico para o Selenium, apenas acho que é uma boa dica para tudo que você faz.
Resumo
O selênio é uma estrutura de testes massiva, e eu apenas toquei a ponta do iceberg neste post. A coisa mais importante a ter em mente ao criar esses testes é: KISS. Mantenha as coisas simples, Slugger. Você pode começar construindo uma cobertura parcial apenas do seu aplicativo da Web, sem precisar seguir com uma solução completa. Isso manterá alguns bugs afastados, e é mais do que você tinha antes.
Gostaria muito de saber quais são os obstáculos que você encontrou na sua implementação e, é claro, sobre os sucessos.
Você já implementa uma estrutura de teste Selenium? Quais são as lições que você aprendeu com sua implementação?
Máxima comunicação com proteção ao extremo? Avance Network: A verdadeira rede social junte-se a nós