Muitas vezes acontece que um aplicativo da Web consiste em um grande número de formulários de reestruturação dinamicamente com texto e controles diferentes. Testar esse aplicativo se transforma em um pesadelo.Você precisa clicar em 100500 páginas e verificar todas as funcionalidades ... E antes do próximo lançamento, verifique o mesmo novamente ... E novamente ... E amanhã novamente. Em algum momento, a verificação começa a demorar mais que o desenvolvimento de novas funcionalidades. "E os testes e2e?" - você pergunta. Mas, primeiro, eles ainda precisam ser escritos. Em segundo lugar, antes de começar a escrevê-los, você precisa escrever casos de teste. Muitos casos de teste.Se, ao ler essas linhas, sua testa estiver coberta de suor, não se preocupe. Neste artigo, compartilharei com você a idéia de como, na Tinkoff, automatizamos o teste de um dos aplicativos da web sem escrever um único caso de teste e teste e2e.
Gravando casos de teste automaticamente
Aconteceu que o teste de nosso aplicativo da Web está principalmente relacionado a verificações de interface. Você precisa verificar se o botão está presente na tela, o título e o texto desejados são exibidos e, quando você insere um valor inválido na entrada , é exibida uma mensagem de erro.Portanto, ao escrever um caso de teste, você precisa registrar todas as ações:- "Pressionou o botão"
- "Introduziu o valor de XXX"
- "Selecionou o valor AAAA na lista suspensa"
e verificações:- "O texto apareceu: XXX"
- "A mensagem de erro apareceu: AAA"
- "O cabeçalho apareceu: ZZZ"
Depois de analisar toda a funcionalidade de nosso aplicativo da web, identificamos cerca de 30 ações e verificações exclusivas. Ficou claro que esse processo pode ser automatizado. Para fazer isso, você só precisa acompanhar todas as ações do testador na página e a reação do site a essas ações.Vamos começar interceptando eventos. Para rastrear a interação com controles como botões, botões de opção e caixas de seleção, você precisa se inscrever no evento click. Cada estrutura possui seus próprios métodos para isso. Por exemplo, fromEvent em Angular e document.addEventListener em JavaScript e React. Para controles de entrada, como calendário ou entrada, apenas o tipo de evento no qual você deseja se inscrever será alterado: em vez de clicar, o foco será.fromEvent(this.elementRef.nativeElement, 'click')
.subscribe(tagName => {
if (tagName === 'BUTTON') {
this.testCaseService.addAction(` "${action.name}"`);
} else if (tagName === 'INPUT-CALENDAR') {
this.testCaseService
.addAction(` "${action.name}" "${action.value}"`);
}
});
E, finalmente, a coisa mais importante é verificar. A maneira como o site deve se comportar em resposta às ações do testador.O que o testador geralmente verifica? Por exemplo, ele inseriu um valor inválido na entrada , o site respondeu com uma mensagem de erro. Ou, digamos, clicamos em um botão e, em resposta, uma nova tela apareceu, o título mudou, um novo texto apareceu e os controles foram reconstruídos. Todas essas alterações estão relacionadas à alteração na árvore do DOM. Existem muitas opções para rastreá-los. Você pode, por exemplo, usar MutationObserver em React e JavaScript ou ngAfterViewInit em Angular (colocando uma diretiva nos elementos do formulário de interesse no site).ngAfterViewInit() {
const tagName = this.nativeElement.nodeName;
const text = this.nativeElement.textContent;
if (['SPAN', 'P'].includes(tagName)) {
this.testCaseService.addContent(`** ** "${text}"\n`);
} else if (tagName === 'H1') {
this.testCaseService.addContent(`** ** "${text}"\n`);
} …
}
O código dependerá muito do layout. Vamos dar uma olhada na marcação. Esses botões são retirados do tradutor do Google.
<div class="tlid-input-button input-button header-button tlid-input-button-text text-icon" role="tab" tabindex="-1">
<div class="text"></div>
</div>
<div class="tlid-input-button input-button header-button tlid-input-button-docs documents-icon" role="tab" tabindex="-1">
<div class="text"></div>
</div>
Apesar do fato de os botões não serem representados como tags de botão , observando a marcação, é possível selecionar todos os botões da página usando a classe css "botão de entrada" e obter nomes de botões da classe css "text" aninhada.Metade do trabalho foi feito, resta apenas anotar tudo o que rastreamos em um caso de teste.Incluímos a interceptação de todas as ações no site para uma combinação de teclas específica e apenas no circuito de teste. Paramos a interceptação de todos os eventos no site por uma certa combinação de teclas. Isso permite iniciar e parar a gravação automática do caso de teste de qualquer lugar.Gravando automaticamente testes e2e
Se você observar o caso de teste gerado automaticamente, esses são essencialmente scripts de usuário reduzidos para o mesmo formulário. Portanto, eles podem ser convertidos em testes e2e. Você pode escrever imediatamente testes e2e imediatamente após interceptar todas as ações e verificações, ignorando os casos de teste.Agora, há um grande número de estruturas diferentes com notação de pepino, com base em scripts comportamentais: SpecFlow, xBehave.net., Cucumber.js, CodeceptJS, etc.Para obter recursos do caso de teste, é necessário adicionar a palavra-chave When antes das ações e antes todas as verificações Then e And.Obtenha o teste e2e gerado automaticamente:Feature: 2-
Background:
When "" ""
Scenario:
When " - "
Then " "
And " - "
When " " ""
When "" " "
When ""
Para executar o teste, os recursos gerados são poucos - você precisa escrever um manipulador para todas as ações e verificações.Há boas notícias: você não precisa escrever um manipulador para cada recurso. Como eu disse, apesar do grande número de formulários diferentes no site, temos apenas 30 ações e verificações exclusivas, o que significa que haverá exatamente o mesmo número de métodos no processador comum para todos os testes do e2e. O código será um pouco diferente - dependendo da estrutura escolhida, com notação e layout de pepino no site. Mas escrever o manipulador em si não leva muito tempo.When(' {string}', async function (button: string) {
const xpath = "//button"
const btn = await getItemByText(xpath, button)
await waitAndClick(btn)
})
When(' {string} {string}', async function (label: string, text: string) {
const xpath = "//*[contains(text(),'" + label + "')]/ancestor::outline"
await inputSendKeys(currentBrowser().element(by.xpath(xpath)), text)
})
Agora, verificando a próxima tarefa, um caso de teste é gravado automaticamente para o testador e o teste e2e gerado automaticamente é executado.Em resumo, você precisa:- Assine eventos de interação com controles e a reação do site a essas ações (por meio do rastreamento da reconstrução da árvore do DOM).
- Converta dados do parágrafo 1 em testes e2e.
- Escreva um manipulador geral para executar testes do e2e.
Essa abordagem ajudará você a se afastar da rotina. Você pode automatizar a gravação de casos de teste e testes e2e para verificações simples relacionadas à interface. Fomos ainda mais longe e verificamos automaticamente também o registro no banco de dados e o envio para serviços de terceiros.Falei sobre isso, bem como sobre a versão, a pilha de tecnologia e até sobre os problemas no primeiro estágio da implementação e sua solução na conferência Heisenbug-2019 em Moscou .Neste artigo, tentei transmitir a ideia principal sem entrar em detalhes.Conclusão
Agora, em média, demoramos 2 minutos para escrever um caso de teste e um teste e2e - isso é 60 vezes mais rápido que os cálculos iniciais, quando queríamos escrever casos de teste e testes e2e manualmente.Não mudamos os processos na equipe. Não era mais necessário alocar a capacidade de teste para escrever casos de teste e levá-la à equipe de automação.Saímos completamente da noção de regressão. Se antes, com uma corrida de duas semanas, a regressão levava mais de três dias, agora a regressão leva tempo para executar todos os testes do e2e, e isso é de apenas 2 horas.Ao escrever manualmente testes e2e, é muito difícil acompanhar os testes. Agora, os testes do e2e são gravados automaticamente durante o teste da tarefa e o testador não precisa verificar a mesma funcionalidade duas vezes.Como resultado, nossa equipe, sem alterar a composição, começou a trabalhar com muito mais eficiência.