Entrega Estável de Produtos com Cypress
Fei Han
February 7, 2021
O Apache APISIX Dashboard foi projetado para tornar o mais fácil possível para os usuários operar o Apache APISIX por meio de uma interface front-end, e desde o início do projeto, houve 552 commits e 10 lançamentos. Com uma iteração de produto tão rápida, é importante garantir a qualidade do produto de código aberto. Por esse motivo, introduzimos um módulo de teste E2E para garantir a entrega estável do produto.
O que é Front-End E2E?
E2E, que significa "End to End", pode ser traduzido como teste "de ponta a ponta". Ele imita o comportamento do usuário, começando com um ponto de entrada e executando ações passo a passo até que uma tarefa seja concluída. Testes sólidos evitam que mudanças no código quebrem a lógica original.
Por que Cypress
Usamos Taiko, Puppeteer, TestCafe e Cypress para escrever casos de teste para criar rotas durante o período de pesquisa de seleção, e usamos cada framework de teste para escrever casos e experimentar suas respectivas características.
O Taiko é caracterizado por um seletor inteligente, que pode localizar de forma inteligente os elementos que você deseja operar com base no conteúdo do texto e nas relações de localização, e tem um baixo custo de inicialização, permitindo que você conclua os casos de teste rapidamente. No entanto, ele não é amigável ao escrever casos de teste. Quando o usuário sai do terminal por engano, todos os casos de teste escritos são perdidos, e se você quiser executar um caso de teste completo, precisa usá-lo junto com outros executores de teste, o que aumenta o custo de aprendizado para o usuário.
O Puppeteer tem o melhor desempenho. No entanto, o teste não é o foco do Puppeteer. Ele é amplamente usado para web crawlers. Nosso projeto começou com o Puppeteer, o framework de teste E2E oficial recomendado pelo ANTD, e após usá-lo por um tempo, descobrimos que o Puppeteer não parecia tão amigável para desenvolvedores que não são de front-end e era difícil envolver outros usuários. Quando os usuários escrevem casos de teste, a falta de posicionamento inteligente de elementos torna a curva de aprendizado muito alta.
O TestCafe é surpreendentemente fácil de instalar, tem um mecanismo de espera embutido para que os usuários não precisem esperar ativamente pelas interações da página, e suporta testes concorrentes em vários navegadores, o que é útil para testes de compatibilidade com vários navegadores. A desvantagem é que seu processo de depuração não é tão amigável, e você precisa executar um novo caso de uso após cada alteração no caso de teste. Para os desenvolvedores, é necessário ter um conhecimento básico de sintaxe Javascript. Além disso, sua velocidade de execução é relativamente lenta em comparação com outros frameworks, especialmente ao executar withText() para encontrar elementos.
Após uma comparação abrangente, finalmente escolhemos o Cypress como nosso framework E2E de front-end, listando quatro razões principais:
- Sintaxe simples
A sintaxe usada nos testes do Cypress é muito simples e fácil de ler e escrever. Com um pouco de prática, você pode dominar a criação de casos de teste, o que é importante para projetos de código aberto, pois permite que a comunidade interessada em casos de teste E2E participe da escrita de casos de teste com um custo de aprendizado mínimo.
- Depuração fácil
Ao depurar casos de teste, podemos usar o Test Runner do Cypress, que apresenta dados multidimensionais que nos permitem identificar rapidamente o problema.
- Mostra o status da execução do caso de teste, incluindo o número de sucessos, falhas e execuções em andamento.
- Exibe o tempo total gasto na execução de todo o conjunto de testes.
- Um Selector Playground embutido para ajudar a localizar elementos.
- Mostra cada etapa de execução para cada caso de uso e forma um snapshot que pode mostrar informações sobre cada etapa de execução após sua conclusão.
- Comunidade ativa
O Cypress tem uma grande comunidade de usuários, e sempre há muitas pessoas dentro da comunidade compartilhando suas experiências e ideias.
Isso é útil ao encontrar problemas, e é provável que você encontre problemas que outros já enfrentaram antes. Além disso, quando novos recursos são solicitados, podemos participar da comunidade discutindo e adicionando recursos ao Cypress que desejamos adicionar, assim como fazemos na comunidade APISIX: ouvindo a comunidade e devolvendo feedback.
- Documentação clara
A estrutura da documentação do Cypress é mais clara e abrangente. Nos estágios iniciais de uso, conseguimos introduzir rapidamente o Cypress em nosso projeto e escrever nosso primeiro caso com base nas diretrizes da documentação oficial. Além disso, há uma grande quantidade de documentação disponível no site da documentação que oferece uma boa orientação sobre as melhores práticas.
Cypress e APISIX Dashboard
Atualmente, há 49 casos de teste escritos para o APISIX Dashboard. Configuramos o CI correspondente no GitHub Action para garantir que o código seja aprovado antes de cada merge, garantindo a qualidade do código. Compartilhamos o uso do Cypress no APISIX Dashboard com você, referenciando as melhores práticas do Cypress e combinando-as com nosso projeto.
- Funções comumente usadas são encapsuladas em comandos.
Tomando o login como exemplo, o login é uma parte essencial para entrar no sistema, então o encapsulamos como um comando, para que o comando de login possa ser chamado antes de cada execução de caso.
Cypress.Commands.add("login", () => {
cy.request(
"POST",
'http://127.0.0.1/apisix/admin/user/login',
{
username: "user",
password: "user",
}
).then((res) => {
expect(res.body.code).to.equal(0);
localStorage.setItem("token", res.body.data.token);
});
});
beforeEach(() => {
// init login
cy.login();
})
- Extrair o seletor e os dados como variáveis públicas.
Para tornar mais intuitivo para o usuário entender o significado do código de teste, extraímos o seletor e os dados como variáveis públicas.
const data = {
name: 'hmac-auth',
deleteSuccess: 'Delete Plugin Successfully',
};
const domSelector = {
tableCell: '.ant-table-cell',
empty: '.ant-empty-normal',
refresh: '.anticon-reload',
codemirror: '.CodeMirror',
switch: '#disable',
deleteBtn: '.ant-btn-dangerous',
};
- Remover cy.wait(someTime)
Usamos cy.wait(someTime) nos primeiros dias do Cypress, mas descobrimos que cy.wait(someTime) depende muito do ambiente de rede e do desempenho da máquina de teste, o que pode causar erros nos casos de teste quando o ambiente de rede ou o desempenho da máquina é ruim. A prática recomendada é usá-lo em conjunto com cy.intercept() para especificar explicitamente os recursos de rede a serem aguardados.
cy.intercept("https://apisix.apache.org/").as("fetchURL");
cy.wait("@fetchURL");
Resumo
Atualmente, o APISIX Dashboard tem 49 casos de teste escritos. No futuro, continuaremos a aumentar a cobertura E2E de front-end e exigiremos que a comunidade concorde em escrever casos de teste para cada nova funcionalidade ou correção de bug submetida, para garantir a estabilidade do produto.
Bem-vindo a se juntar a nós para aprimorar o produto de gateway de classe mundial.
Endereço do projeto: https://github.com/apache/apisix-dashboard