Ao escrever um software, você pode confirmar se ele funciona corretamente por meio de testes. Teste pode ser amplamente definido como o processo de execução de software em ambientes para garantir que ele se comporte conforme o esperado.
Testes bem-sucedidos podem dar a você a confiança de que, à medida que adicionar novos códigos, recursos ou e até mesmo atualizar suas dependências, o software que você já escreveu continuem a funcionar da maneira que você espera. Os testes também ajudam a proteger de software contra cenários improváveis ou entradas inesperadas.
Alguns exemplos de comportamentos na Web que convém testar incluem:
- Garantir que o recurso de um site funcione corretamente quando um botão é clicado.
- Confirmação de que uma função complexa produz os resultados corretos.
- Concluir uma ação que exige o login do usuário.
- Verificar se um formulário informa corretamente um erro quando dados incorretos são inseridos.
- Garantir que um aplicativo da web complexo continue funcionando quando um usuário baixa largura de banda ou fica off-line.
Comparação entre testes automatizados e manuais
É possível testar o software de duas maneiras gerais: testes automatizados e manuais testes.
O teste manual envolve pessoas executando software diretamente, como carregar um site no navegador e confirmar que ele se comporta como esperado. Manualmente os testes são simples de criar ou definir. Por exemplo, seu site pode carregar? Você consegue realizar essas ações? — mas cada execução custa uma quantia enorme do tempo do ser humano. Embora os humanos sejam muito criativos, isso pode permitir um tipo de teste conhecidos como testes exploratórios, ainda podemos ser ineficientes em notar falhas ou e inconsistências, especialmente ao realizar a mesma tarefa muitas vezes.
Testes automatizados são qualquer processo que permita a codificação e execução dos testes repetidamente por um computador para confirmar o comportamento pretendido do software sem pedir para que uma pessoa realize as etapas repetidas, como configurar ou verificar os resultados. É importante ressaltar que, depois que o teste automatizado é configurado, ele pode ser executado com frequência. Essa ainda é uma definição muito ampla, e é importante notar que os testes assumem todos os tipos de formas. A maioria do curso aborda com testes automatizados como prática.
Os testes manuais têm seu lugar, geralmente como um precursor da programação mas também quando os testes automatizados se tornam muito não confiáveis, têm um escopo amplo, ou difícil de escrever.
Os fundamentos com um exemplo
Para nós, como desenvolvedores Web que escrevem JavaScript ou linguagens relacionadas, um resumo o teste automatizado pode ser um script assim que você executa todos os dias, talvez pelo Node ou pelo navegador:
import { fibonacci } from "../src/math.js";
if (fibonacci(0) !== 0) {
throw new Error("Invalid 0th fibonacci result");
}
const fib13 = fibonacci(13);
if (fib13 !== 233) {
throw new Error("Invalid 13th fibonacci result, was=${fib13} wanted=233");
}
Este é um exemplo simplificado que fornece os seguintes insights:
Este é um teste, porque ele executa algum software (a API Fibonacci) ) e garante que comportamento funciona da maneira esperada, verificando seus resultados em relação valores esperados. Se o comportamento não estiver correto, ocorrerá um erro, que A expressão JavaScript gera uma
Error
.Mesmo que você esteja executando este script manualmente em seu terminal ou um navegador, esse teste ainda é automatizado porque pode ser executado repetidamente sem que você precise executar nenhuma etapa individual. A próxima página, em que a execução de testes, explica mais sobre isso.
Embora esse teste não use nenhuma biblioteca, a biblioteca é o JavaScript que pode executar em qualquer lugar. Ainda é um teste. Há muitas ferramentas que podem ajudar você escrever testes, incluindo aqueles que serão abordados mais tarde neste curso, todas elas ainda trabalham com o princípio fundamental de causar um erro se se algo der errado.
Como testar bibliotecas na prática
A maioria das bibliotecas ou frameworks de teste integrados fornece duas primitivas principais que facilitar a criação de testes: declarações e uma maneira de definir testes independentes; Elas serão abordadas em detalhes na próxima seção, declarações e outros primitivos. No entanto, de modo geral, é importante lembrar que quase todos os testes que você vê ou programa acaba usando esses tipos de primitivos.
As declarações são uma forma de combinar a verificação de um resultado e causar um erro
se algo der errado. Por exemplo, você pode tornar o teste anterior mais conciso
introduzindo assert
:
import { fibonacci } from "../src/math.js";
import { assert } from "a-made-up-testing-library";
assert.equal(fibonacci(0), 0, "Invalid 0th fibonacci result");
assert.equal(fibonacci(13), 233, "Invalid 13th fibonacci result");
É possível melhorar ainda mais esse teste definindo testes independentes, como opção agrupadas em pacotes. O pacote a seguir testa de forma independente o conjunto de dados e a função Catalão:
import { fibonacci, catalan } from "../src/math.js";
import { assert, test, suite } from "a-made-up-testing-library";
suite("math tests", () => {
test("fibonacci function", () => {
assert.equal(fibonacci(0), 0, "Invalid 0th fibonacci result");
assert.equal(fibonacci(13), 233, "Invalid 13th fibonacci result");
});
test("relationship between sequences", () => {
const numberToCheck = 4;
const fib = fibonacci(numberToCheck);
const cat = catalan(numberToCheck);
assert.isAbove(fib, cat);
});
});
Neste contexto de teste de software, teste como um substantivo se refere a um caso de teste: um cenário único, independente e endereçável, como a "relação entre sequências" no caso de teste anterior.
Os testes nomeados individualmente são úteis para as seguintes tarefas, entre outras:
- Determinar como um teste é bem-sucedido ou falha ao longo do tempo.
- Destacar um bug ou cenário pelo nome para que você possa testar mais facilmente se o for resolvido.
- Execução de alguns testes independentemente de outros, como por meio de um filtro glob.
Uma maneira de pensar em casos de teste é usar os "três As" do teste de unidade: organizar, agir e declarar. Cada caso de teste, em sua essência, vai:
- Organize alguns valores ou estados, que podem ser dados de entrada codificados.
- Executar uma ação, como chamar um método.
- Declare os valores de saída ou o estado atualizado (usando
assert
).
Escala dos testes
Os exemplos de código na seção anterior descrevem um teste de unidade, porque eles testar partes menores do seu software, concentrando-se frequentemente em um único arquivo, e nesse caso, apenas a saída de uma única função. A complexidade dos testes aumenta conforme você considerar códigos de vários arquivos, componentes ou até mesmo diferentes (às vezes fora de seu controle, como um serviço de rede ou os comportamento de uma dependência externa). Por isso, os tipos de teste geralmente são nomeados com base no escopo ou na escala deles.
Além dos testes de unidade, alguns exemplos de outros tipos incluem testes de componentes testes, testes visuais e testes de integração. Nenhum desses nomes tem definições rigorosas que podem ter significados diferentes, dependendo por isso, lembre-se de usá-los como um guia e chegar a definições que que funcionam para você. Por exemplo, o que está um componente em teste no sistema? Para desenvolvedores do React, isso pode literalmente mapear para um "componente do React", mas pode têm significados diferentes para os desenvolvedores em outros contextos.
A escala de um teste individual pode ser colocada dentro de um conceito chamado como a "pirâmide de teste", o que pode ser uma boa regra prática para o que um teste e como ela é executada.
Essa ideia foi iterada, e várias outras formas já foram popularizado, como o diamante de teste ou o para testar o cone de gelo. As prioridades da criação de testes provavelmente serão exclusivas das suas de código aberto. No entanto, um recurso comum é que testes mais simples, como testes de unidade, tendem a ser mais rápidas de executar, mais fáceis de escrever (assim, você terá mais delas) e testam um escopo limitado, enquanto testes complexos como testes completos são difícil de escrever, mas pode testar um escopo mais amplo. Na verdade, a camada superior teste de "formas" tende a ser um teste manual, porque alguma interação do usuário é muito complexas para serem codificadas em um teste automatizado.
Esses tipos serão expandidos em tipos de modelos para testes.
Teste seu conhecimento
Quais primitivos a maioria das bibliotecas e frameworks de teste oferecem?
assert()
e suas variações tendem a ser incluídas, pois facilitam as verificações
gravação.test()
está incluído em quase todos os testes
de corrida. Ela é importante porque o código de teste não é executado no nível superior
de um arquivo, o que permite que o executor trate cada caso de teste como uma
uma unidade independente.