Este artigo ainda não foi publicado e não é visível para os motores de busca.
Teste Visual em Monorepo: Como Não Testar 47 Projetos a Cada Commit

Teste Visual em Monorepo: Como Não Testar 47 Projetos a Cada Commit

Um monorepo (repositório monolítico) é uma arquitetura de gerenciamento de código-fonte onde múltiplos projetos, aplicações e bibliotecas compartilhadas coexistem em um único repositório Git, gerenciados por ferramentas de orquestração como Nx, Turborepo ou Lerna que otimizam builds e testes com base no grafo de dependências.

Os monorepos venceram. Equipes front-end que gerenciam múltiplas aplicações — um site de marketing, um dashboard administrativo, um app do cliente, um portal de parceiros — agrupam tudo em um único repositório. É mais simples para compartilhar código, mais consistente para o design system, mais eficiente para atualizações transversais.

Mas para o teste visual, é um pesadelo logístico. Não porque o teste visual não funcione em monorepo. Funciona perfeitamente. O problema é que funciona bem demais: uma mudança em um pacote compartilhado dispara potencialmente testes visuais em todos os projetos que dependem dele. E quando seu monorepo contém 15, 30 ou 50 projetos, "testar tudo a cada commit" deixa de ser uma opção.

O problema fundamental: o grafo de dependências

Em um monorepo, os projetos não são independentes. Eles compartilham pacotes: um design system, uma biblioteca de utilitários, componentes comuns, configurações compartilhadas. Essas dependências formam um grafo — e é esse grafo que torna o teste visual complexo.

Tomemos um exemplo concreto. Você tem um pacote "ui-components" contendo seus botões, formulários e componentes de navegação. Esse pacote é usado por 12 aplicações no seu monorepo. Você modifica o padding de um botão em "ui-components". Visualmente, essa mudança potencialmente afeta todas as 12 aplicações. Cada página que contém um botão pode renderizar de forma diferente.

Se você roda testes visuais nas 12 aplicações, está potencialmente capturando centenas de screenshots. O pipeline CI/CD leva 45 minutos. Os desenvolvedores esperam. E se um teste falha — um falso positivo por um problema de renderização headless — o desenvolvedor do pacote "ui-components" tem que investigar uma falha em uma aplicação que ele nem conhece.

É insustentável. E é exatamente o que acontece em monorepos que não têm uma estratégia de teste visual.

Testar o que mudou, não tudo: o princípio de afetação

A primeira regra do teste visual em monorepo é simples na teoria, complexa na prática: testar apenas o que foi afetado pela mudança.

As ferramentas de monorepo modernas — Nx e Turborepo à frente — sabem calcular o grafo de dependências e identificar os projetos "afetados" por uma mudança. Quando você modifica um arquivo no pacote "ui-components", o Nx pode dizer que as aplicações A, C, F e K dependem desse pacote, mas não B, D e as outras.

É a base. Mas para o teste visual, não é suficiente. Porque "a aplicação A depende de ui-components" não significa que todas as páginas da aplicação A usam o componente modificado. Se você alterou o botão, apenas as páginas que contêm um botão são afetadas. Páginas sem botão são estáveis.

O teste visual inteligente em monorepo opera portanto em dois níveis de filtragem. Primeiro nível: quais projetos são afetados pela mudança, segundo o grafo de dependências. Segundo nível: quais páginas ou componentes desses projetos realmente usam o elemento modificado.

O primeiro nível é resolvido pelas ferramentas de monorepo. O segundo nível é muito mais difícil — requer análise estática do código (quais páginas importam qual componente) ou um mapeamento explícito mantido pela equipe (este componente é usado nestas páginas).

A realidade dos pacotes compartilhados

Os pacotes compartilhados são a força e a fraqueza do monorepo. Permitem a consistência: um único design system, uma única fonte de verdade para os componentes visuais. Mas também criam um blast radius considerável.

Há três tipos de pacotes compartilhados que trazem problemas específicos para o teste visual.

Os pacotes de componentes UI. É o caso mais evidente. Uma mudança em um botão, formulário ou modal afeta visualmente todas as páginas que os utilizam. O blast radius é proporcional à popularidade do componente. Um componente de layout usado em todo lugar (Header, Footer, Sidebar) tem blast radius máximo.

Os pacotes de estilos e tokens. Uma mudança nos design tokens — cores, espaçamentos, tipografias — frequentemente é invisível no grafo de dependências tradicional. Se você modifica a cor primária no seu arquivo de tokens, o grafo vê uma mudança no pacote "design-tokens". Mas essa mudança afeta visualmente tudo: cada botão primário, cada link, cada elemento acentuado em todas as aplicações. O blast radius é total.

Os pacotes de utilitários com efeitos visuais colaterais. Menos óbvios: funções utilitárias que formatam datas, truncam texto ou calculam layouts. Uma mudança em uma função de truncamento de texto — de 100 para 80 caracteres máximos — tem impacto visual direto em todos os componentes que a usam. Mas o grafo de dependências não sabe que é uma mudança "visual".

As estratégias que funcionam

Após observar dezenas de equipes gerenciarem o teste visual em monorepos, estas são as estratégias que produzem os melhores resultados.

Estratégia 1: o teste visual por camadas

Organize seus testes visuais em três camadas com diferentes frequências de execução.

A camada de componente. Teste cada componente do design system isoladamente, via Storybook ou equivalente. Esses testes rodam apenas quando o pacote de componentes muda. São rápidos (alguns minutos) e protegem a biblioteca em si. É a primeira rede de segurança, a descrita no artigo sobre os testes visuais em design systems.

A camada de página afetada. Teste as páginas das aplicações afetadas pela mudança, identificadas pelo grafo de dependências. Esses testes rodam em cada pull request, mas apenas nos projetos afetados. São o núcleo da sua estratégia.

A camada completa. Teste todas as páginas de todas as aplicações. Essa camada não roda em cada PR — é muito custosa. Execute-a uma vez por dia (nightly), ou antes de cada release. Ela captura regressões que o grafo de dependências não conseguiu prever.

Estratégia 2: o mapeamento componente-página explícito

Mantenha um arquivo de configuração que associe cada componente compartilhado às páginas que o utilizam. Quando o componente Button muda, o arquivo indica que as páginas /login, /signup, /checkout e /settings da aplicação A usam esse componente. Apenas essas páginas são testadas.

Esse mapeamento é tedioso para manter manualmente. Mas pode ser gerado automaticamente por análise estática do código — percorrendo os imports de cada página e subindo as dependências. Nx oferece plugins que facilitam esse tipo de análise.

A vantagem é considerável: em vez de testar 200 páginas da aplicação A quando um componente muda, você testa apenas 12. O pipeline cai de 30 minutos para 3 minutos.

Estratégia 3: a baseline compartilhada com override

Em um monorepo com design system compartilhado, as baselines visuais (screenshots de referência) têm uma particularidade: os componentes compartilhados têm o mesmo renderizado em todas as aplicações (em teoria). Você pode portanto manter uma baseline do design system no nível do pacote e só recapturar baselines no nível das aplicações quando o contexto de integração muda.

Concretamente: quando você modifica o componente Button, atualiza a baseline do Button no pacote ui-components. As aplicações que usam o Button herdam essa nova baseline. Apenas as aplicações onde o Button renderiza de forma diferente no contexto (por CSS específico, tema ou override) precisam de suas próprias baselines.

Os erros clássicos a evitar

Testar tudo, o tempo todo. É a reação natural, e a pior. Seus pipelines ficam lentos, seus desenvolvedores ignoram os resultados porque há muito ruído, e os bugs reais se afogam em falsos positivos. O teste visual em monorepo deve ser cirúrgico.

Ignorar o grafo de dependências. Algumas equipes configuram seus testes visuais independentemente da ferramenta de monorepo. Resultado: os testes não sabem quais projetos são afetados e testam tudo ou nada. Integre sua ferramenta de teste visual com Nx ou Turborepo. Use seus comandos "affected" para disparar os testes certos.

Colocar todas as baselines em uma única pasta. As baselines visuais devem viver ao lado dos projetos que protegem. Se você centraliza todas as baselines em uma pasta raiz, perde a granularidade: não sabe mais qual baseline pertence a qual projeto, e a limpeza de baselines obsoletas se torna impossível.

Negligenciar o versionamento de baselines durante atualizações transversais. Quando você modifica um design token que afeta todos os projetos, todas as baselines devem ser atualizadas simultaneamente. Se você as atualiza projeto por projeto em PRs separadas, cria uma janela onde alguns projetos têm as novas baselines e outros as antigas. Os testes se tornam inconsistentes.

O papel do CI/CD no teste visual de monorepo

A configuração CI/CD é crítica. Seu pipeline deve ser capaz de três coisas.

Primeiro, calcular o conjunto de projetos afetados pela mudança. É o trabalho do Nx (nx affected) ou Turborepo (turbo run --filter). Essa etapa determina o escopo dos testes.

Segundo, paralelizar os testes visuais por projeto. Se três aplicações são afetadas, rode os testes das três aplicações em paralelo, não em sequência. Cada aplicação tem seu próprio conjunto de baselines e seu próprio relatório de resultados. A paralelização é a única forma de manter tempos de pipeline aceitáveis.

Terceiro, agregar os resultados e bloquear a PR se necessário. Mesmo que os testes sejam paralelizados, o veredito final deve ser único: a PR passa ou não passa. Se a aplicação A tem uma regressão visual e as outras não, a PR é bloqueada. O desenvolvedor sabe exatamente qual aplicação está afetada e pode investigar.

Quando o no-code simplifica tudo

As ferramentas de teste visual baseadas em código — Playwright, Cypress com plugins visuais — se integram bem em um monorepo porque vivem no mesmo repositório, ao lado do código que testam. Mas adicionam código de teste para manter, configurações por projeto e scripts CI/CD específicos.

As ferramentas no-code como a Delta-QA propõem uma abordagem diferente. Em vez de testar a partir do código-fonte, testam a partir das URLs implantadas. Você configura as URLs de cada aplicação, a ferramenta captura os screenshots e compara com as baselines. O monorepo não é mais um fator de complexidade — a ferramenta só vê URLs, não pacotes.

A desvantagem: você não se beneficia do grafo de dependências para filtrar os testes. A vantagem: a configuração é instantânea, não há código de teste para manter, e o teste é independente da arquitetura do repositório. Para equipes que não têm desenvolvedores dedicados a testes, é frequentemente o compromisso certo.

FAQ

Nx ou Turborepo é melhor para teste visual em monorepo?

Nx tem uma vantagem significativa graças ao seu grafo de dependências mais detalhado e seus plugins de análise estática. O comando nx affected identifica com precisão os projetos impactados, e os executors Nx permitem integrar tarefas de teste visual no grafo de tarefas. Turborepo é mais simples mas oferece filtragem menos granular.

Como gerenciar as baselines quando um design token muda e afeta tudo?

Trate como uma atualização transversal. Crie uma PR dedicada que modifique o token e atualize todas as baselines afetadas em uma única operação. Execute a camada completa de testes visuais, aprove as mudanças esperadas em lote e faça merge. Nunca fragmente uma atualização de token em múltiplas PRs — é a porta aberta para inconsistências.

Quanto tempo um teste visual deveria levar em um pipeline monorepo?

Mirando apenas os projetos afetados: menos de 10 minutos para uma PR padrão tocando um único projeto. Menos de 20 minutos para uma mudança em um pacote compartilhado afetando 3 a 5 projetos. Se seus testes levam mais de 30 minutos em uma PR, sua estratégia de filtragem é insuficiente. A camada completa (nightly) pode demorar mais — 30 a 60 minutos é aceitável.

Devem existir baselines separadas por ambiente (dev, staging, prod)?

Sim, se os ambientes têm conteúdos ou configurações diferentes. Não, se a renderização é idêntica. Na prática, mantenha uma única baseline por projeto, capturada em um ambiente de staging estável. Comparar contra produção é tentador, mas o conteúdo dinâmico (datas, dados de usuário, testes A/B) gera falsos positivos demais.

O teste visual em monorepo funciona com Lerna?

Lerna é principalmente uma ferramenta de gerenciamento de versões e publicação de pacotes. Seu grafo de dependências é menos sofisticado que o do Nx ou Turborepo. Você pode usá-lo, mas provavelmente precisará complementar com um script personalizado para identificar os projetos afetados. Se está começando um novo monorepo, prefira Nx ou Turborepo.

Como evitar que os desenvolvedores ignorem os resultados do teste visual?

Três regras. Mantenha a taxa de falsos positivos próxima de zero — se os desenvolvedores veem falsos positivos regularmente, param de olhar. Bloqueie PRs em caso de falhas no teste visual — sem merge sem aprovação. E mantenha os tempos de pipeline curtos — se o teste visual adiciona 45 minutos à PR, os desenvolvedores encontrarão formas de contorná-lo.


Para aprofundar


O monorepo é uma excelente arquitetura para o compartilhamento de código e a consistência. Mas sem uma estratégia de teste visual adaptada, ele transforma cada mudança em uma loteria: esse commit quebrou algo em um projeto que eu nem conheço? A resposta a essa pergunta nunca deveria ser "não sei". Deveria ser automática, rápida e confiável.

Experimente a Delta-QA Gratuitamente →