Teste de Snapshot
Testes de snapshot são ferramentas bem úteis sempre que você desejar garantir que sua UI não seja alterada inesperadamente.
Um típico caso de teste de snapshot para um app móvel renderizar um componente UI, leva uma captura de tela, em seguida compara com uma imagem de referência armazenada juntamente com o teste. O teste irá falhar se as duas imagens não coincidirem: quer a mudança seja inesperada, ou a captura de tela precisa ser atualizada para a nova versão do componente da UI.
Testes de Snapshot com Jest #
Uma abordagem semelhante pode ser tomada quando se trata de testar seus componentes React. Em vez de renderizar a interface gráfica do usuário, ou UI, que iria precisar construir o aplicativo inteiro, você pode usar um renderizador de teste para gerar rapidamente um valor serializável para sua árvore React. Considere este exemplo de teste para um simples componente de Link:
import React from 'react'; import Link from '../Link.react'; import renderer from 'react-test-renderer'; it('renders correctly', () => { const tree = renderer.create( <Link page="http://www.facebook.com">Facebook</Link> ).toJSON(); expect(tree).toMatchSnapshot(); });
A primeira vez que esse teste é executado, Jest cria um arquivo de snapshot que se parece com isto:
exports[`renders correctly 1`] = ` <a className="normal" href="http://www.facebook.com" onMouseEnter={[Function]} onMouseLeave={[Function]} > Facebook </a> `;
O artefato do snapshot deve ser comitado (committed, em inglês) junto com as alterações de código, e revisado como parte de seu processo de revisão de código. Jest usa pretty-format para fazer snapshots legíveis durante a revisão do código. Em execuções de teste subsequentes Jest simplesmente irá comparar a saída renderizada com o snapshot anterior. Se eles coincidirem, o teste passará. Se eles não coincidirem, ou o executor de teste encontrou um bug em seu código que deve ser corrigido, ou a implementação foi alterada e o snapshot precisa ser atualizado.
Mais informações sobre como testes de snapshot funcionam e por que o construímos podem ser encontradas no post de lançamento no blog. Nós recomendamos ler este post no blog para obter uma boa base de quando você deve usar teste de snapshot. Também recomendamos assistir este vídeo no egghead sobre Testes de Snapshot com Jest.
Atualizando Snapshots #
É simples de detectar quando um snapshot falhar depois que um bug foi introduzido. Quando isso acontecer, vá em frente e corrija o problema e certifique-se de que seus testes de snapshot estão passando novamente. Agora, vamos falar sobre o caso de quando um teste de snapshot está falhando devido a uma alteração intencional da implementação.
Uma situação assim pode ocorrer se nós intencionalmente mudarmos o endereço que para onde o componente Link aponta em no nosso exemplo.
// Teste atualizado com um Link para um endereço diferente it('renders correctly', () => { const tree = renderer.create( <Link page="http://www.instagram.com">Instagram</Link> ).toJSON(); expect(tree).toMatchSnapshot(); });
Nesse caso, Jest irá imprimir esta saída:
Uma vez que acabamos de atualizar nosso componente para apontar para um endereço diferente, é razoável esperar mudanças no snapshot para este componente. Nosso caso de teste de snapshot está falhando porque o snapshot para nosso componente atualizado já não coincide com o artefato de snapshot para este caso de teste.
Para resolver esse problema, precisamos atualizar nossos artefatos de snapshot. Você pode executar Jest com uma flag que irá dizer para re-gerar snapshots:
jest --updateSnapshot
Vá em frente e aceite as alterações executando o comando acima. Você também pode usar o caractere único equivalente -u
como flag para re-gerar snapshots, se preferir. Isso irá re-gerar artefatos de snapshot para todos testes de snapshot que falharam. Se tivéssemos mais algum teste de snapshot falhando devido a um bug não intencional, precisamos corrigir o bug antes de re-gerar snapshots para evitar a gravação de snapshot do bug.
Se você gostaria de limitar quais casos de teste snapshot devem ser gerados novamente, você pode passar uma flag adicional --testNamePattern
para re-gravar snapshots somente para aqueles testes que correspondem ao padrão.
Você pode experimentar essa funcionalidade por clonar o exemplo de snapshot, modificando o componente Link
e executando Jest.
Testes Devem ser Determinísticos #
Seus testes devem ser determinísticos. Ou seja, executar os mesmos testes várias vezes em um componente que não foi alterado devem produzir os mesmos resultados todas as vezes. Você é responsável por certificar-se de que seus snapshots gerados não incluem dados específicos de plataforma ou outros não determinísticos.
Por exemplo, se você tem um componente Clock que usa Date.now()
, o snapshot gerado a partir deste componente será diferente cada vez que o caso de teste é executado. Neste caso podemos simular o método Date.now() para retornar um valor consistente toda vez que o teste é executado:
Date.now = jest.fn(() => 1482363367071);
Agora, toda vez que o caso de teste de snapshot é executado, Date.now()
retornará consistentemente 1482363367071
. Isso resultará no mesmo snapshot sendo gerado para este componente independentemente de quando o teste é executado.
Snapshots não são gravados automaticamente em sistemas de integração contínua (CI, Continuous Integration) #
A partir do Jest 20, snapshots em Jest não são automaticamente gravados quando Jest é executado em um sistema de CI sem explicitamente passar --updateSnapshot
. Espera-se que todos os snapshots são parte do código que é executado em CI e como novos snapshots passam automaticamente, eles não devem passar um teste executado em um sistema de CI. É recomendável sempre dar commit em todos os snapshots e mantê-los no controle de versão.
Perguntas Frequentes #
Arquivos de snapshot devem ser comitados (committed, em inglês)? #
Sim, todos os arquivos de snapshot devem ser comitados juntamente com os módulos que eles cobrem e seus testes. Eles devem ser considerados como parte de um teste, similar ao valor de qualquer outra verificação em Jest. Na verdade, snapshots representam o estado dos módulos fonte em qualquer ponto no tempo. Desta forma, quando os módulos fonte são modificados, Jest pode dizer o que mudou da versão anterior. Também pode fornecer um monte de contexto adicional durante a revisão do código na qual os revisores podem estudar melhor as alterações.
Teste de snapshot só funciona com componentes React? #
Componentes React e React Native são um bom caso de uso para testes de snapshot. No entanto, snapshots podem capturar qualquer valor que pode ser serializado e devem ser usados sempre que o objetivo é testar se a saída é correta. O repositório Jest contém muitos exemplos de testes da saída do próprio Jest, a saída da biblioteca de verificação do Jest, bem como mensagens de log de várias partes do código do Jest. Veja um exemplo de saída CLI de snapshotting no repositório do Jest.
Qual é a diferença entre teste de snapshot e teste de regressão visual? #
Teste de snapshot e teste de regressão visual são duas maneiras distintas de testar interfaces de usuário, ou UIs, e eles servem para finalidades diferentes. Ferramentas de teste de regressão visual tiram screenshots de páginas da web e comparam as imagens resultantes pixel por pixel. Com testes de snapshot, valores são serializados, armazenados dentro de arquivos de texto e comparados usando um algoritmo de comparação. Existem diferentes trade-offs básicos a considerar e nós listamos as razões porque teste de snapshot foi construído no blog do Jest.
Teste de snapshot substitui teste unitário? #
Teste de snapshot é apenas um das mais de 20 verificações que acompanham Jest. O objetivo do teste de snapshot não é substituir os testes unitários existentes, mas fornecer valor adicional e tornar fazer testes algo fácil. Em alguns cenários, teste de snapshot podem potencialmente eliminar a necessidade de testes unitários para um determinado conjunto de funcionalidades (por exemplo, componentes React), mas também podem trabalhar juntos.
Qual é o desempenho do teste de snapshot no que diz respeito a velocidade e tamanho dos arquivos gerados? #
Jest foi reescrito tendo desempenho em mente, e teste de snapshot não é uma exceção. Como os snapshots são armazenados dentro de arquivos de texto, esta forma de teste é rápida e confiável. Jest gera um novo arquivo para cada arquivo de teste que invoca o matcher toMatchSnapshot
. O tamanho dos snapshots são bem pequenos: para referência, o tamanho de todos os arquivos de snapshot da base de código do Jest em si é menos de 300 KB.
Como eu resolvo conflitos dentro de arquivos de snapshot? #
Arquivos de snapshot sempre devem representar o estado atual dos módulos que estão cobrindo. Portanto, se você estiver mesclando dois "branches" e encontra um conflito nos arquivos de snapshot, você pode ou resolver o conflito manualmente ou atualizar o arquivo de snapshot executando Jest e inspecionar o resultado.
É possível aplicar os princípios de desenvolvimento orientado a testes com teste de snapshot? #
Embora seja possível escrever arquivos de snapshot manualmente, isto geralmente não é amigável. Snapshots ajudam a descobrir se a saída dos módulos cobertos pelos testes foi alterada, ao invés de dar orientações para projetar o código em primeiro lugar.
Cobertura de código funciona com testes de snapshot? #
Sim, tal como com qualquer outro teste.