Como iniciar o teste de unidade do seu código JavaScript


Todos sabemos que devemos escrever testes de unidade. Mas é difícil saber por onde começar e quanto tempo dedicar aos testes em comparação à implementação real. Então, por onde começar? E trata-se apenas de testar código ou os testes de unidade têm outros benefícios?

Neste artigo, explicarei os diferentes tipos de testes e quais benefícios os testes de unidade trazem para as equipes de desenvolvimento. Vou mostrar o Jest – uma estrutura de teste de JavaScript.

Diferentes tipos de teste

Antes de nos aprofundarmos nas especificidades dos testes de unidade, quero fazer uma rápida análise dos diferentes tipos de testes. Muitas vezes há alguma confusão ao seu redor e não estou surpreso. Às vezes a linha entre eles é bastante fina.

Testes unitários

Os testes de unidade testam apenas uma parte da sua implementação. Uma unidade. Sem dependências ou integrações, sem especificações de estrutura. Eles são como um método que retorna um link em um idioma específico:

export function getAboutUsLink(language){
  switch (language.toLowerCase()){
    case englishCode.toLowerCase():
      return '/about-us';
    case spanishCode.toLowerCase():
      return '/acerca-de';
  }
  return '';
}

Testes de integração

Em algum momento, seu código se comunica com um banco de dados, sistema de arquivos ou outro terceiro. Pode até ser outro módulo no seu aplicativo.

Essa parte da implementação deve ser testada por testes de integração. Eles geralmente têm uma configuração mais complicada que envolve a preparação de ambientes de teste, a inicialização de dependências e assim por diante.

Testes funcionais

Testes de unidade e testes de integração garantem que seu aplicativo funcione. Os testes funcionais examinam o aplicativo do ponto de vista do usuário e testam se o sistema funciona conforme o esperado.

No diagrama acima, você vê que os testes de unidade formam a grande base do conjunto de testes do seu aplicativo. Normalmente, eles são pequenos, existem muitos e são executados automaticamente.

Então agora vamos entrar em testes de unidade com mais detalhes.

Por que devo me preocupar em escrever testes de unidade?

Sempre que pergunto aos desenvolvedores se eles escreveram testes para seu aplicativo, eles sempre me dizem: “Não tive tempo para eles” ou “Não preciso deles, sei que funciona”.

Então, eu sorrio educadamente e digo a eles o que quero lhe dizer. Os testes de unidade não são apenas sobre testes. Eles também ajudam você de outras maneiras, para que você possa:

Esteja certo de que seu código funciona. Quando foi a última vez que você confirmou uma alteração no código, sua compilação falhou e metade do seu aplicativo parou de funcionar? A minha foi na semana passada.

Mas ainda está tudo bem. O problema real é quando a compilação é bem-sucedida, a alteração é implantada e o aplicativo começa a ficar instável.

Quando isso acontece, você começa a perder a confiança no seu código e, eventualmente, apenas ora para que o aplicativo funcione. Os testes de unidade o ajudarão a descobrir problemas muito mais cedo e a ganhar confiança.

Tome melhores decisões de arquitetura. O código é alterado, mas algumas decisões sobre plataforma, módulos, estrutura e outras precisam ser tomadas durante os estágios iniciais de um projeto.

Quando você começa a pensar no teste de unidade logo no início, ele ajuda a estruturar melhor seu código e a obter uma separação adequada das preocupações. Você não será tentado a atribuir várias responsabilidades a blocos de código único, pois isso seria um pesadelo para o teste de unidade.

Identifique a funcionalidade antes da codificação. Você escreve a assinatura do método e começa a implementá-lo imediatamente. Ah, mas o que deve acontecer caso um parâmetro seja nulo? E se o seu valor estiver fora do intervalo esperado ou contiver muitos caracteres? Você lança uma exceção ou retorna nulo?

Os testes de unidade ajudarão você a descobrir todos esses casos. Examine as perguntas novamente e você descobrirá exatamente o que define seus casos de teste de unidade.

Tenho certeza de que há muitos outros benefícios em escrever testes de unidade. Estes são apenas os que me lembro da minha experiência. Aqueles que eu aprendi da maneira mais difícil.

Como escrever seu primeiro teste de unidade JavaScript

Mas vamos voltar ao JavaScript. Vamos começar com Jest, que é uma estrutura de teste de JavaScript. É uma ferramenta que permite o teste automático de unidade, fornece cobertura de código e permite que nós zombemos dos objetos com facilidade. Jest também tem uma extensão para o Visual Studio Code disponivel aqui.

Também existem outras estruturas, se você estiver interessado, pode verificá-las Este artigo.

npm i jest --save-dev

Vamos usar o método mencionado anteriormente getAboutUsLink como implementação, queremos testar:

const englishCode = "en-US";
const spanishCode = "es-ES";
function getAboutUsLink(language){
    switch (language.toLowerCase()){
      case englishCode.toLowerCase():
        return '/about-us';
      case spanishCode.toLowerCase():
        return '/acerca-de';
    }
    return '';
}
module.exports = getAboutUsLink;

Eu coloquei isso no index.js Arquivo. Podemos escrever testes no mesmo arquivo, mas uma boa prática é separar os testes de unidade em um arquivo dedicado.

Os padrões de nomenclatura comuns incluem {filename}.test.js e {filename}.spec.js. Eu usei o primeiro index.test.js:

const getAboutUsLink = require("./index");
test("Returns about-us for english language", () => {
    expect(getAboutUsLink("en-US")).toBe("/about-us");
});

Primeiro, precisamos importar a função que queremos testar. Todo teste é definido como uma invocação do test função. O primeiro parâmetro é o nome do teste para sua referência. A outra é uma função de seta na qual chamamos a função que queremos testar e especifica qual resultado esperamos. Eu

Nesse caso, chamamos getAboutUsLink funcionar com en-US como o parâmetro language. Esperamos que o resultado seja /about-us.

Agora podemos instalar a CLI Jest globalmente e executar o teste:

npm i jest-cli -g
jest

Se você vir um erro relacionado à configuração, verifique se possui o seu package.json arquivo presente. Caso contrário, gere um usando npm init.

Você deve ver algo assim:

 PASS  ./index.test.js
  √ Returns about-us for english language (4ms)
  console.log index.js:15
    /about-us
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        2.389s

Bom trabalho! Este foi o primeiro teste simples de unidade JavaScript do início ao fim. Se você instalou a extensão de código do Visual Studio, ela executará testes automaticamente quando você salvar um arquivo. Vamos tentar estendendo o teste com esta linha:

expect(getAboutUsLink("cs-CZ")).toBe("/o-nas");

Depois de salvar o arquivo, o Jest informará que o teste falhou. Isso ajuda a descobrir possíveis problemas antes mesmo de confirmar suas alterações.

Testando a funcionalidade avançada e os serviços de zombaria

Na vida real, os códigos de idioma para o método getAboutUsLink não seriam constantes no mesmo arquivo. Seu valor é normalmente usado em todo o projeto, para que sejam definidos em seu próprio módulo e importados para todas as funções que os utilizam.

import { englishCode, spanishCode } from './LanguageCodes'

Você pode importar essas constantes para o teste da mesma maneira. Mas a situação ficará mais complicada se você estiver trabalhando com objetos em vez de constantes simples. Dê uma olhada neste método:

import { UserStore } from './UserStore'
function getUserDisplayName(){
  const user = UserStore.getUser(userId);
  return `${user.LastName}, ${user.FirstName}`;
}

Este método usa importados UserStore:

class User {
    getUser(userId){
        // logic to get data from a database
    }
    setUser(user){
        // logic to store data in a database
    }
}
let UserStore = new User();
export { UserStore }

Para testar adequadamente esse método, precisamos zombar UserStore. Um mock é um substituto para o objeto original. Ele nos permite separar dependências e dados reais da implementação do método testado, assim como os manequins ajudam nos testes de colisão de carros em vez de pessoas reais.

Se não usássemos o mock, estaríamos testando essa função e a loja. Isso seria um teste de integração e provavelmente precisaríamos zombar do banco de dados usado.

Zombando de um serviço

Para simular objetos, você pode fornecer uma função de simulação ou uma simulação manual. Vou me concentrar no último, pois tenho um caso de uso claro e simples. Mas fique à vontade para confira outras possibilidades de zombaria que o Jest oferece.

jest.mock('./UserStore', () => ({
    UserStore: ({
        getUser: jest.fn().mockImplementation(arg => ({
            FirstName: 'Ondrej',
            LastName: 'Polesny'
        })),
        setUser: jest.fn()
    })
}));

Primeiro, precisamos especificar o que estamos zombando – o ./UserStore módulo. Em seguida, precisamos retornar a simulação que contém todos os objetos exportados desse módulo.

Nesta amostra, é apenas o User objeto chamado UserStore com a função getUser. Mas com implementações reais, o mock pode ser muito mais longo. Todas as funções com as quais você realmente não se importa no escopo de teste de unidade podem ser facilmente zombadas jest.fn().

O teste de unidade para o getUserDisplayName A função é semelhante à que criamos antes:

test("Returns display name", () => {
    expect(getUserDisplayName(1)).toBe("Polesny, Ondrej");
})

Assim que eu salvo o arquivo, Jest me diz que tenho 2 testes aprovados. Se você estiver executando testes manualmente, faça-o agora e verifique o mesmo resultado.

Relatório de Cobertura de Código

Agora que sabemos como testar o código JavaScript, é bom cobrir o máximo de código possível com os testes. E isso é difícil de fazer. No final, somos apenas pessoas. Queremos concluir nossas tarefas e os testes de unidade geralmente produzem uma carga de trabalho indesejada que costumamos ignorar. A cobertura de código é uma ferramenta que nos ajuda a combater isso.

A cobertura do código informará o tamanho de uma parte do seu código coberta por testes de unidade. Tomemos, por exemplo, meu primeiro teste de unidade verificando o getAboutUsLink função:

test("Returns about-us for english language", () => {
   expect(getAboutUsLink("en-US")).toBe("/about-us");
});

Ele verifica o link em inglês, mas a versão em espanhol permanece não testada. A cobertura do código é de 50%. O outro teste de unidade está verificando a getDisplayName funcione completamente e sua cobertura de código é 100%. Juntos, a cobertura total do código é de 67%. Tivemos três casos de uso para testar, mas nossos testes cobrem apenas dois deles.

Para ver o relatório de cobertura de código, digite o seguinte comando no terminal:

jest --coverage

Ou, se você estiver usando o Visual Studio Code com a extensão Jest, poderá executar o comando (CTRL + SHIFT + P) Brincadeira: Alternar sobreposição de cobertura. Ele mostrará na implementação quais linhas de código não são cobertas com testes.

Ao executar a verificação de cobertura, o Jest também criará um relatório HTML. Encontre-o na pasta do projeto em coverage/lcov-report/index.html.

Agora, não preciso mencionar que você deve se esforçar para obter 100% de cobertura de código, certo? 🙂

Sumário

Neste artigo, mostrei como começar com o teste de unidade em JavaScript. Embora seja bom ter uma cobertura de código de 100% no relatório, na realidade, nem sempre é possível (significativamente) chegar lá. O objetivo é permitir que os testes de unidade o ajudem a manter seu código e garantir que ele sempre funcione conforme o esperado. Eles permitem que você:

  • definir claramente os requisitos de implementação,
  • melhor projetar seu código e separar preocupações,
  • descubra problemas que você pode apresentar com seus commits mais recentes,
  • e dê a você a confiança de que seu código funciona.

O melhor lugar para começar é o Começando na documentação do Jest para que você possa experimentar essas práticas por si mesmo.

Você tem sua própria experiência com código de teste? Eu adoraria ouvir, me avise Twitter ou junte-se a um dos meus Twitch streams.





Fonte

Leave a Reply

Your email address will not be published. Required fields are marked *