DEV Community

Adriana Ferreira Lima Shikasho
Adriana Ferreira Lima Shikasho

Posted on • Edited on

[pt-BR] Conheça a melhor forma de escrever testes no seu front-end - #2

Como vimos na Parte 1, testar detalhes de implementação no front-end pode ser uma armadilha que pode acabar mascarando erros gerando falso-positivos ou falso-negativos ou até mesmo atrapalhando a produtividade por serem muito frágeis.

Vamos então abordar de maneira prática um caminho para se pensar em testes no front-end de forma que eles se tornem mais confiáveis e com mais qualidade.

O que será abordado:

  • Testando Casos de Uso
  • Cobertura de Código
  • Cobertura de Casos de Uso
  • Quando a Cobertura de Código oculta os Casos de Uso

Testando Casos de Uso

"Quanto mais seus testes se assemelham à forma como seu software é usado, mais confiança eles podem lhe dar." - Kent C. Dodds

Essa é a natureza dos testes de casos de uso, pensar em escrever testes que atendam a forma que nossos dois usuários** (usuário-final e usuário-desenvolvedor) usam e interagem com nossa aplicação.

**ver Detalhes de implementação da parte 1

Escrevemos testes para ter certeza de que nosso aplicativo funcionará quando o usuário os usar e principalmente melhorar a confiança da aplicação.

"Pense menos no código que você está testando e mais nos casos de uso que o código suporta." - Kent C. Dodds

Cobertura de Código

Cobertura de código é a métrica que nos mostra quais linhas do nosso código estão rodando durante o teste. Vamos utilizar esse código como exemplo:

function verificaArray(array) {
  if (Array.isArray(array)) return array
  else if (!array) return []
  else return [array]
}
Enter fullscreen mode Exit fullscreen mode

Sem incluir teste para essa função, o relatório vai indicar que 0% de Cobertura de código nos dando a ideia de quanta parte do código ainda falta cobrir.

O relatório de Cobertura de código não diz exatamente qual a importância da função verificaArray ou nem mesmo diz os casos de uso que ela atende.

Mas quando consideramos a aplicação inteira, mesmo o relatório de Cobertura de código não nos dando uma a visão completa, ele nos ajuda a identificar quais testes poderiam ser adicionados para atender os casos de uso da aplicação.

Cobertura de Casos de Uso

A Cobertura de Casos de Uso nos diz quantos casos de uso nosso teste atende. Voltando ao código de exemplo, podemos identificar o primeiro caso de uso da função verificaArray:

  • "Retorna um array se o argumento for um array".

Obs: Há uma convenção de escrever os títulos dos testes em inglês, entretanto neste estudo, vou escrevê-los em português-BR por uma questão didática, beleza?

test('Retorna um array se o argumento for um array', () => {
  expect(verificaArray(['Elefante', 'Girafa']))
  .toEqual(['Elefante', 'Girafa'])
})
Enter fullscreen mode Exit fullscreen mode

E com esse teste escrito, nosso relatório de Cobertura de Código vai parecer com algo do tipo:

function verificaArray(array) {          // coberto
  if (Array.isArray(array)) return array // coberto
  else if (!array) return []
  else return [array]
}
Enter fullscreen mode Exit fullscreen mode

Assim, se olharmos para as linhas que faltam, vamos concluir que são mais dois casos de Uso que faltam ser cobertos:

  • "Retorna um array vazio se o argumento tiver um valor falso"
  • "Retorna um array se o argumento não for um array e não for falso"

Vamos adicionar os testes para esses casos de uso, e ver como isso afeta a Cobertura de Código

test(
'Retorna um array vazio se o argumento tiver um valor falso', () => {
   expect(verificaArray()).toEqual([])
})

test(
`Retorna um array se o argumento não for um array e não for falso`,
() => {
  expect(verificaArray('Leopardo')).toEqual(['Leopardo'])
})
Enter fullscreen mode Exit fullscreen mode

Cobertura:

function verificaArray(array) {          // coberto
  if (Array.isArray(array)) return array // coberto
  else if (!array) return []             // coberto
  else return [array]                    // coberto
}
Enter fullscreen mode Exit fullscreen mode

Ótimo! Agora temos 100% de cobertura de código, mas também 100% de cobertura de casos de uso e podemos confiar que, enquanto não mudarmos os casos de uso dessa função, nossos testes vão continuar passando.

Quando a cobertura de código oculta os casos de uso

As vezes, o relatório de Cobertura de código pode indicar 100% de cobertura, mas não 100% de cobertura de casos de uso.

Esse é o motivo que é bom ter a prática de pensar em todos os casos de uso possíveis antes mesmo de começar a escrever os testes.

Por exemplo, vamos imaginar que a function verificaArray foi implementada desse jeito:

function verificaArray(array) {         
  if (Array.isArray(array)) return array
  else return [array].filter(Boolean)                   
}
Enter fullscreen mode Exit fullscreen mode

Com isso, nós temos 100% de cobertura com apenas os 2 casos de uso:

  • Retorna um array se o argumento for um array
  • Retorna um array se o argumento não for um array

Entretanto, se olharmos para o relatório de Cobertura de caso de uso, podemos perceber que está faltando um caso de uso:

  • Retorna um array vazio se o argumento tiver um valor falso

E isso é um mau sinal, pois mesmo se o usuário user a função verificaArray sem passar nenhum argumento, os testes vão continuar passando, mas o código vai quebrar.

E essa é justamente uma das razões que implementamos testes, garantir que o código continue atendendo aos casos de uso que desejamos incluir.

Por exemplo, se um outro dev remover o .filter(Boolean), os testes ainda continuam passando, mas qualquer código que dependia do resultado da function como sendo "falso", vai quebrar.

👉 Continue lendo na parte 3


Referências:
"How to know what to test" - Kent C. Dodds
https://kentcdodds.com/blog/how-to-know-what-to-test
"Avoid the Test User" - Kent C. Dodds
https://kentcdodds.com/blog/avoid-the-test-user
"Testing Implementation Details" - Kent C. Dodds
https://kentcdodds.com/blog/testing-implementation-details

Top comments (0)