Regression Testing
Luciano Ratamero

Luciano Ratamero

24 Mar 2023 6 min read

Conhecendo Testes de Regressão Visual

Ter trabalhado no design system da Labcodes me deu um apreço enorme por testes robustos. Poder confiar que minhas refatorações não vão quebrar nada ajuda muito em um projeto que exige componentes de alta flexibilidade. No entanto, nossa cobertura atual de testes não garante o mais importante: que as mudanças não afetaram o comportamento visual dos componentes. Na pesquisa por uma solução, descobri a maravilha dos testes de regressão visual.

O que são?

Testes de Regressão Visual são testes que literalmente tiram um print de uma parte da sua interface e garantem que seu visual não mudou desde a última vez que os testes foram rodados. Eles se integram bem com ferramentas para testes de integração/e2e como Cypress e Playwright, que já usam navegadores para rodar os testes. Conceitualmente, se parecem muito com testes de snapshots, mas, em vez de guardarem a estrutura do HTML de um componente, eles guardam uma imagem em disco.

UI of one of the image diff tools with images generated by a visual regression test
UI of one of the image diff tools with images generated by a visual regression test

Em geral, esse tipo de teste é útil para cenários em que bugs visuais acontecem com muita frequência. São perfeitos para design systems, bibliotecas de componentes, ou como testes de saúde da aplicação, garantindo que algum elemento essencial esteja sempre sendo exibido corretamente em produção.

Esse tipo de teste, no entanto, exige um certo nível de configuração caso você não esteja usando algo como o Playwright ou o Cypress para fazê-lo. Assim como os de snapshot, é muito raro que testes de regressão visual vivam por si só; é bem mais comum que essas verificações sejam feitas no final de testes já existentes.

Temos duas grandes vertentes de testes de regressão visual: com verificação automática junto a sua suíte de testes; e com verificação manual através de serviços como o Percy.

Primeira abordagem: com verificação automática

Essa abordagem é mais própria para times pequenos, nos quais a presença de uma pessoa de design ou negócio é um pouco mais limitada. Nela, adicionamos ao final dos testes uma chamada à verificação automática, de uma forma quase idêntica a testes de snapshot:

Código de exemplo de um teste end-to-end com verificação de regressão visual
Código de exemplo de um teste end-to-end com verificação de regressão visual

No caso do Playwright, todo o setup e configuração já estão prontos; basta adicionar uma nova asserção que ele irá guardar em disco um print do componente:

await expect(locator).toHaveScreenshot('filename.png')

O Cypress é um pouco mais complicado, já que ele não vem com essa funcionalidade por padrão. Recomendo usar algo como o @frsource/cypress-plugin-visual-regression-diff, que já é compatível com o Cypress >= 10. Essa abordagem, apesar de ser conveniente, gratuita e razoavelmente fácil de se configurar, tem alguns contras a serem considerados.

Contras da abordagem automática

Ao meu ver, essa abordagem tem dois contras: compatibilidade entre navegadores e OSs e tamanho das imagens no repositório.

Cada navegador e OS renderiza interfaces web de formas levemente diferentes - diferentes o suficiente para que comparação de imagens se torne algo muito difícil de ser feito. Por exemplo, se seu time tem pessoas devs usando macOS e Linux, as imagens geradas já vão ser diferentes.

Para resolver esse problema, recomendo que esse tipo de teste seja rodado dentro de um container Docker, até para que nosso CI possa rodar esses testes e não encontre problemas. Temos exemplos no código que vamos deixar de referência no final do post. Um detalhe é que eu tive que personalizar a imagem do Cypress, que não estava funcionando no meu Mac M1 (a do Playwright funcionou sem alterações).

O outro problema, o do tamanho das imagens no repositório, na minha opinião, não é um problema tão grande assim. Antes de tudo, temos que ter em mente que esse tipo de verificação não é pra ser feita em todos os testes, só os mais importantes. Por exemplo, se temos um botão e ele pode ter um ícone dentro, só adicionamos testes visuais para a renderização padrão e a com ícone.

Outro fator é de que as imagens são, em geral, bem pequenas. A do teste acima, por exemplo, gerou uma imagem de 23k. Mesmo que essas imagens se acumulem ao longo de anos de projeto, acho difícil que elas deixem seu repositório maior do que uma única imagem do Docker; e elas só terão que ser baixadas uma vez, na hora de clonar o projeto. Também há formas de removê-las do histórico do git, caso isso se torne um problema real.

Segunda abordagem: com verificação manual

Outra forma de termos testes de regressão visual é usando ferramentas como o Percy ou o BackstopJS. Essas plataformas foram feitas para equipes maiores, que tenham uma presença mais ativa de pessoas de design, QA ou negócio.

Nessa abordagem, podemos adicionar ao final dos nossos testes uma chamada ao plugin da ferramenta escolhida. Ela ficará encarregada de tirar os prints, fazer o upload para o site da ferramenta e apresentar uma interface para revisão dos prints.

Essa abordagem é preferível para times que tenham um fluxo de desenvolvimento mais lento e burocrático, ou empresas que querem um controle maior da equipe de design ou negócio no produto que está sendo feito.

Interface do Percy para verificação visual de alterações de layout
Interface do Percy para verificação visual de alterações de layout

Contras da abordagem manual

Apesar de não necessitar que testes rodem em containers e de não adicionar imagens ao repositório, esse tipo de abordagem tende a ser pior para o dia a dia de uma equipe de desenvolvimento, na minha opinião, já que não é automática. Primeiro, esses serviços tendem a ser muito limitados no plano gratuito, o que significa que você terá que pagar para ter acesso a builds de mais de um mês atrás - e essas ferramentas em geral não são baratas.

Outro fator a ser considerado é o de que criamos um gargalo burocrático na mão da pessoa que revisa. Caso sua equipe ou empresa não tenha pessoas fixas para esse serviço (uma pessoa de QA, design ou produto), isso pode gerar uma lentidão maior no processo de desenvolvimento. Existem casos em que essa burocracia é desejada, mas esse ponto precisa ser bem explícito antes de se adotar essa abordagem.

Por fim, um detalhe: se você quer que seus Pull Requests não possam fazer merge antes da confirmação de mudança de um dos prints, você precisa conectar o Percy ao Github dentro das configurações do Percy. Sem isso, seu PR no Github será marcado como pronto para sofrer merge.

Exibição de duas verificações de um pull request no Github: uma passando com sucesso quando não deveria e outra quebrando da maneira que deve, por haverem mudanças visuais de layout
Exibição de duas verificações de um pull request no Github: uma passando com sucesso quando não deveria e outra quebrando da maneira que deve, por haverem mudanças visuais de layout

Testes, testes, testes

No final das contas, o importante mesmo é testar. Testes de regressão visual são somente mais uma ferramenta a ser adicionada no nosso cinto de utilidades, e é uma ferramenta para ser usada com cuidado e parcimônia. Deixo aqui as referências, e caso tenha alguma dúvida ou sugestão, pode mandar pra gente nos comentários. Obrigado, e até a próxima!

Referências