O lazy loading (carregamento diferido) é uma técnica de otimização web que atrasa o carregamento de recursos não visíveis — imagens, vídeos, componentes, dados — até ao momento em que o utilizador faz scroll para a zona da página onde aparecem, reduzindo assim o tempo de carregamento inicial e o consumo de largura de banda.
Eis o paradoxo que poucas equipas querem ouvir: o lazy loading é excelente para os seus utilizadores e terrível para os seus testes visuais. É uma tecnologia concebida para não carregar conteúdo até que seja visível. Mas uma ferramenta de teste visual precisa de ver o conteúdo para o testar. Os dois objetivos estão fundamentalmente em tensão.
Esta tensão não é uma razão para escolher um em detrimento do outro. O seu site precisa de lazy loading para ter bom desempenho — os dados da Google são claros, o tempo de carregamento é um fator de ranking SEO e um determinante maior da taxa de rejeição. E o seu site precisa de testes visuais para garantir que o lazy loading não introduz regressões — um placeholder que nunca desaparece, uma imagem que carrega com as dimensões erradas, um layout que salta quando o conteúdo aparece.
Este artigo explica como conciliar ambos.
Por que o lazy loading complica o teste visual
O conteúdo invisível não pode ser testado
O princípio fundamental do lazy loading é que o conteúdo abaixo da linha de flutuação (below the fold) não é carregado no carregamento inicial da página. Um screenshot tirado imediatamente após o carregamento mostra apenas o conteúdo acima da linha de flutuação — tudo o resto está ausente ou substituído por placeholders.
É um problema de cobertura. Se a sua página tem 5.000 píxeis de altura e o seu viewport mede 900 píxeis, um screenshot inicial cobre apenas 18% da sua página. Os 82% restantes não são testados. Numa página de produto e-commerce, isto significa que a descrição, as opiniões dos clientes, os produtos recomendados e o footer nunca são verificados visualmente.
Algumas equipas pensam resolver o problema tirando um screenshot full-page. Mas um screenshot full-page não ativa o lazy loading — captura a página tal como está renderizada no momento da captura, com os placeholders e os elementos não carregados. Obtém uma imagem completa de uma página incompleta.
O momento da captura: um dilema permanente
Quando exatamente deve tirar o seu screenshot? A pergunta parece simples. Não é.
Se tirar o screenshot imediatamente após o carregamento da página, captura o estado inicial com os placeholders. É rápido mas incompleto. Se fizer scroll até ao fundo da página antes de capturar, ativa o carregamento de todo o conteúdo diferido — mas enquanto cada recurso carrega, o conteúdo no topo da página pode ter mudado (animações, atualizações em tempo real, reexibição do header).
E ainda, o próprio scroll modifica a aparência da página. Um header sticky que aparece ao fazer scroll, um botão "voltar ao topo" que se materializa, um indicador de progresso de leitura que se preenche — todos estes elementos mudam conforme a posição de scroll, e o seu estado no momento da captura varia de uma execução para outra.
Os placeholders de imagem e o layout shift
O lazy loading de imagens usa placeholders para reservar espaço no layout: retângulos cinzentos, desfocados de baixa resolução (LQIP — Low Quality Image Placeholder), SVGs coloridos, ou simplesmente nada. Quando a imagem real carrega, substitui o placeholder.
O problema surge quando a substituição do placeholder pela imagem modifica as dimensões do elemento. É o famoso Cumulative Layout Shift (CLS) — um deslocamento visível que move os elementos circundantes. Se o seu screenshot é tirado durante este deslocamento, captura um estado transitório que não é nem o placeholder nem o estado final.
As boas práticas web recomendam definir dimensões explícitas nas imagens (width e height em HTML) para evitar o layout shift. Mas nem todas as equipas seguem estas boas práticas, e as imagens responsive com dimensões variáveis tornam a coisa mais complexa.
O infinite scroll: uma página sem fim
O infinite scroll leva o problema do lazy loading ao extremo. Em vez de uma página de tamanho fixo com conteúdo diferido, tem uma página cujo comprimento é potencialmente infinito. Cada scroll para baixo carrega novos elementos e alonga a página.
Como testa visualmente uma página sem fim? Não pode capturar um screenshot full-page — a página não tem "full". Tem de decidir arbitrariamente quando parar de fazer scroll, quantos elementos constituem uma amostra suficiente, e como gerir o facto de que o conteúdo carregado pelo infinite scroll é frequentemente alimentado por dados que mudam (novos artigos, novas publicações, novos produtos).
O infinite scroll cria também um problema de memória. Cada lote de conteúdo carregado adiciona elementos ao DOM. Após scrolls suficientes, o navegador pode abrandar, a renderização pode tornar-se menos fluida, e o timing das operações pode variar — introduzindo não-determinismo nos seus testes.
As estratégias para testar visualmente o conteúdo em lazy loading
Estratégia 1: o scroll incremental com capturas múltiplas
Em vez de procurar um screenshot único de toda a página, divida a página em segmentos e capture cada segmento separadamente. Faça scroll da altura de um viewport, espere que o conteúdo diferido carregue, capture um screenshot, e continue.
Esta abordagem produz uma série de screenshots — viewport 1, viewport 2, viewport 3, etc. — que compara individualmente com as suas baselines respetivas. Cada screenshot cobre um segmento específico da página com todo o conteúdo carregado.
A vantagem é que obtém cobertura completa com conteúdo totalmente carregado. A desvantagem é a multiplicidade de baselines a manter e a gestão do timing entre cada scroll e cada captura.
Para o infinite scroll, defina um número fixo de scrolls (por exemplo 5 ou 10) e teste os segmentos correspondentes. Não pode testar o infinito, mas pode testar uma amostra representativa.
Estratégia 2: forçar o carregamento completo antes da captura
Algumas ferramentas permitem desativar o lazy loading no ambiente de teste. O atributo HTML loading="eager" força o carregamento imediato de todas as imagens. Os scripts Intersection Observer podem ser patcheados para considerar que todos os elementos são visíveis imediatamente. Os frameworks como React e Vue que implementam lazy loading ao nível do componente podem ser configurados para carregar todos os componentes em modo de teste.
Esta abordagem transforma a sua página com lazy loading numa página completamente carregada, e pode capturar um screenshot full-page clássico. É simples, direto, e resolve o problema de cobertura.
Mas já não está a testar o lazy loading em si. Se a sua implementação de lazy loading tem um bug — um componente que nunca carrega, um placeholder que fica exibido, uma animação de transição que parte o layout — não o verá em modo "eager". Está a testar o conteúdo, não o mecanismo de carregamento.
É um compromisso aceitável se o seu objetivo é unicamente detetar regressões visuais no design. Se também quer verificar que o lazy loading funciona corretamente, precisa da estratégia seguinte.
Estratégia 3: testar os estados de transição
Em vez de contornar o lazy loading, teste-o explicitamente. Capture screenshots em cada etapa do ciclo de carregamento: o estado inicial com os placeholders, o estado durante o carregamento (transição), e o estado final com o conteúdo completo.
Cada estado tem a sua própria baseline. O teste do estado inicial verifica que os placeholders estão corretamente dimensionados e posicionados. O teste do estado final verifica que o conteúdo carregado substitui corretamente os placeholders sem partir o layout. O teste de transição verifica que não há layout shift excessivo.
Esta abordagem é a mais completa mas também a mais pesada de manter. Três baselines por componente com lazy loading são três vezes mais manutenção quando o design evolui. Reserve-a para os componentes críticos onde o comportamento do lazy loading é essencial para a experiência do utilizador.
Estratégia 4: a comparação estrutural, indiferente ao conteúdo de píxeis
A abordagem estrutural resolve elegantemente vários problemas do lazy loading simultaneamente. Em vez de comparar os píxeis de um placeholder e os píxeis da imagem final, compara a estrutura do elemento: a sua posição no DOM, as suas dimensões calculadas, as suas propriedades CSS, a sua visibilidade.
Um placeholder corretamente dimensionado ocupa o mesmo espaço que a imagem final — a estrutura é idêntica mesmo que os píxeis sejam completamente diferentes. Um componente com lazy loading que carrega corretamente mantém a mesma posição e as mesmas dimensões que o seu placeholder. A abordagem estrutural valida esta equivalência sem se preocupar com o conteúdo de píxeis das imagens.
É a abordagem que o Delta-QA usa nativamente. Quando um placeholder de 400x300 píxeis é substituído por uma imagem de 400x300 píxeis, a estrutura não muda — sem alerta. Quando um placeholder de 400x300 é substituído por uma imagem de 400x200 (um bug na proporção), a estrutura muda — alerta legítimo.
Os desafios específicos do infinite scroll
O infinite scroll merece atenção particular porque combina os problemas do lazy loading com desafios que lhe são próprios.
O problema da repetibilidade
O infinite scroll geralmente carrega conteúdo paginado de uma API. O conteúdo da página 2 depende do que está na página 1. Se o conjunto de dados muda entre duas execuções de teste (um novo artigo publicado, um produto retirado), as páginas não têm o mesmo conteúdo, e a comparação falha.
Para obter resultados repetíveis, deve congelar os dados subjacentes. Use uma API mockada que devolva sempre os mesmos dados na mesma ordem, ou teste contra um ambiente de staging com um conjunto de dados fixo.
O problema da renderização de margens e agrupamento
As listas com infinite scroll exibem frequentemente conteúdo com cabeçalhos de agrupamento — "Hoje", "Ontem", "Semana passada". Estes cabeçalhos dependem da data corrente e mudam de um dia para o outro. Um artigo publicado "hoje" estará sob o cabeçalho "Ontem" amanhã.
A solução é a mesma que para qualquer conteúdo temporal: congele a data do sistema no ambiente de teste.
O problema do desempenho degradado
Após 20 ou 30 scrolls sucessivos, o desempenho do navegador pode degradar-se pelo número de elementos no DOM. Esta degradação afeta o timing da renderização e pode introduzir não-determinismo nos seus screenshots.
As aplicações bem concebidas implementam virtualização — mantêm no DOM apenas os elementos atualmente visíveis, reciclando nós DOM à medida que o utilizador faz scroll. Se a sua aplicação virtualiza o DOM, o número de elementos mantém-se constante independentemente do número de scrolls, e o desempenho permanece estável.
Se a sua aplicação não usa virtualização, limite o número de scrolls nos seus testes para permanecer na zona de desempenho aceitável.
Recomendações práticas para integrar o lazy loading na sua estratégia de teste visual
Para as imagens com lazy loading, o mínimo é testar o estado final — o estado onde todas as imagens visíveis no viewport estão carregadas. Use o scroll incremental para ativar o carregamento, espere pela estabilização, e capture. Defina expectativas claras: todas as imagens do viewport devem estar carregadas (sem placeholders visíveis), e nenhum layout shift deve ocorrer após o carregamento.
Para os componentes com lazy loading (code splitting, dynamic imports), teste em dois modos: o modo "tudo carregado" para verificar a renderização dos componentes, e o modo "carregamento natural" para verificar os estados de transição e os fallbacks.
Para o infinite scroll, defina um perímetro de teste realista. Teste os 3 a 5 primeiros carregamentos (scrolls), o que cobre o comportamento inicial, a lógica de paginação, e a transição entre lotes. Não tente testar a totalidade do fluxo — não é prático nem necessário.
Para os placeholders, teste-os explicitamente. Os placeholders fazem parte da experiência do utilizador — um placeholder mal dimensionado causa layout shift, um placeholder ausente deixa um espaço branco na página. Capture um screenshot do estado inicial (antes do scroll) e verifique que os placeholders estão corretamente dimensionados e posicionados.
Para o timing, prefira as esperas condicionais aos atrasos fixos. Espere que as imagens estejam carregadas (via o evento load nos elementos img) em vez de esperar um número arbitrário de segundos. Os atrasos fixos são frágeis — 2 segundos podem bastar localmente e ser insuficientes em CI sob carga.
O lazy loading é um aliado, não um inimigo
O lazy loading otimiza o desempenho do seu site. Reduz o tempo de carregamento inicial, o consumo de largura de banda e a utilização de recursos do lado do cliente. São benefícios reais e mensuráveis para os seus utilizadores.
O facto de complicar o teste visual não é uma razão para abandoná-lo — é uma razão para adaptar a sua estratégia de teste. E as ferramentas modernas de teste visual, o Delta-QA à cabeça, estão concebidas para gerir esta complexidade sem que tenha de escolher entre desempenho e testabilidade.
O lazy loading não é um obstáculo ao teste visual. É uma restrição técnica com soluções técnicas. Implemente-as, e terá o melhor dos dois mundos: páginas rápidas e testes fiáveis.
FAQ
O lazy loading torna o teste visual full-page impossível?
Não, mas requer uma abordagem diferente do screenshot full-page clássico. Ou força o carregamento completo (loading="eager") antes da captura, ou faz scroll progressivamente capturando cada segmento separadamente. Ambas as abordagens oferecem cobertura completa — a primeira é mais simples, a segunda é mais fiel ao comportamento real da página.
Como testar visualmente uma página com infinite scroll?
Defina um perímetro de teste realista: 3 a 5 scrolls cobrem o comportamento inicial, a lógica de paginação, e as transições entre lotes. Use dados mockados para garantir a repetibilidade. Capture cada segmento como um screenshot independente com a sua própria baseline. Não tente testar o infinito — teste uma amostra representativa e fiável.
Deve-se desativar o lazy loading no ambiente de teste?
Depende do seu objetivo. Se testa o conteúdo (detetar regressões visuais no design), desative o lazy loading para simplificar as capturas. Se testa o mecanismo de carregamento (verificar que os placeholders, as transições e o carregamento diferido funcionam), mantenha o lazy loading ativado e teste explicitamente os diferentes estados.
Como gerir o layout shift causado pelo carregamento diferido de imagens?
Defina sempre dimensões explícitas (width e height) nas suas imagens para reservar espaço no layout. Use placeholders do mesmo tamanho que a imagem final (LQIP ou retângulos coloridos). Teste visualmente o estado inicial (com placeholders) e o estado final (com imagens) para verificar que as dimensões não mudam e que nenhum deslocamento ocorre.
Os testes visuais com lazy loading são mais lentos que os testes clássicos?
Sim, necessariamente. O scroll incremental com esperas de carregamento em cada passo leva mais tempo que uma captura instantânea de uma página completamente carregada. É o custo da cobertura completa. Otimize paralelizando os seus testes, limitando o número de scrolls ao estritamente necessário, e usando esperas condicionais em vez de atrasos fixos para minimizar o tempo de espera.
O Delta-QA gere o lazy loading e o infinite scroll?
Sim. A abordagem estrutural do Delta-QA é particularmente adequada ao lazy loading porque compara a estrutura em vez dos píxeis. Um placeholder corretamente dimensionado e a imagem final têm a mesma estrutura — sem falso positivo. A ferramenta gere o scroll incremental, as esperas de carregamento, e a comparação por segmentos, tudo sem escrever uma linha de código.
Para aprofundar
- Teste Visual para Ruby on Rails: Por Que as View Specs Não Bastam e Como o Teste Visual Preenche a Lacuna
- Teste Visual de Progressive Web Apps (PWA): Teste-as Como Apps, Não Como Sites
O lazy loading otimiza o desempenho do seu site. O Delta-QA assegura que não introduz regressões visuais. Os dois não são incompatíveis — são complementares. Teste as suas páginas dinâmicas com o mesmo rigor que as suas páginas estáticas.