Capítulo 18
Os testes passam
4 min de leitura 706 palavras 1 gravura
Um teste é um combinado escrito em código: “se eu chamar somar(2, 3), quero 5”. Enquanto o combinado falhar, a função ainda não está pronta. Este capítulo não pede HTML novo. Você implementa funções em funcoes.js até a página ficar verde.
O exemplo está em exemplos/18-testes/. Abra index.html. A pasta já tem uma versão que passa. Para treinar, esvazie o corpo das funções e reescreva uma por vez.
Não use npm, Node nem Jasmine. O corredor dos testes é um arquivo local: testes.js.
Trabalhe na cópia inicio desta etapa. Leia e digite o código indicado; mude apenas uma coisa. Antes de recarregar, escreva o resultado que espera. Depois compare com a referência completa ao lado. Se algo falhar, confira primeiro o arquivo salvo e o caminho aberto.
O que você vai aprender
- Distinguir o arquivo que você edita (
funcoes.js) do arquivo que descreve o combinado (testes.js). - Ler
esperar(valor).ser(esperado). - Implementar
somar,dobrar,maior,contem,invertereordenar. - Ordenar com o método da bolha: comparar vizinhos e trocar.
Não comece mexendo em testes.js
index.html carrega dois scripts, nesta ordem:
<script src="funcoes.js"></script>
<script src="testes.js"></script>
Primeiro as funções existem. Depois os testes as chamam. Se inverter a ordem, o navegador reclama que somar não existe.
testes.js já traz o corredor. Não o altere no começo. Se você mudar o combinado para “passar de qualquer jeito”, o exercício perde o sentido.
function esperar(obtido) {
return {
ser(esperado) {
const ok = Object.is(obtido, esperado) ||
JSON.stringify(obtido) === JSON.stringify(esperado);
const linha = document.createElement("li");
linha.className = ok ? "ok" : "fail";
linha.textContent = ok
? "passou"
: `falhou: obtido ${JSON.stringify(obtido)} / esperado ${JSON.stringify(esperado)}`;
document.getElementById("resultado").append(linha);
}
};
}
esperar recebe o que a sua função devolveu. ser compara com o valor combinado. Se for igual, a linha fica verde. Se não, a mensagem mostra os dois lados.
Erro comum: apagar uma linha de teste para “ficar verde”. O combinado some, o problema não. Comente no máximo as linhas seguintes para focar num teste. Depois descomente.

Um teste por vez
Os seis combinados no fim de testes.js são estes:
esperar(somar(2, 3)).ser(5);
esperar(dobrar(4)).ser(8);
esperar(maior([3, 9, 4])).ser(9);
esperar(contem(["cerâmica", "xilo"], "xilo")).ser(true);
esperar(inverter("farol")).ser("loraf");
esperar(ordenar([3, 1, 2])).ser([1, 2, 3]);
Abra funcoes.js. Deixe só a primeira função funcionando. Recarregue. Leia a primeira falha. Corrija. Só então olhe a segunda.
Pare e experimente. Coloque return 0; em somar. Recarregue. A primeira linha deve falhar com obtido 0 e esperado 5. Volte o return a + b.
somar, dobrar e maior
function somar(a, b) {
return a + b;
}
function dobrar(n) {
return n * 2;
}
maior percorre um array e guarda o maior valor visto até agora. Começa no índice 0.
function maior(lista) {
let atual = lista[0];
for (let i = 1; i < lista.length; i += 1) {
if (lista[i] > atual) atual = lista[i];
}
return atual;
}
Se a lista for [3, 9, 4], atual começa 3, vira 9 e permanece 9.
contem e inverter
contem responde se o valor está na lista. includes já faz isso.
function contem(lista, valor) {
return lista.includes(valor);
}
O nome da função está sem acento de propósito: identificador em JavaScript neste volume fica em ASCII.
inverter vira o texto ao contrário. "farol" vira "loraf". Uma forma curta: quebrar em letras, inverter o array, juntar de novo.
function inverter(texto) {
return texto.split("").reverse().join("");
}
split("") vira ["f", "a", "r", "o", "l"]. reverse troca a ordem. join("") cola sem separador.
ordenar com bolha
O último teste pede [1, 2, 3] a partir de [3, 1, 2]. Bolha compara cada item com o vizinho da direita. Se estiver fora de ordem, troca. Repete até ninguém precisar trocar.
Faça uma cópia com slice(). Assim a lista original não muda.
function ordenar(lista) {
const copia = lista.slice();
for (let i = 0; i < copia.length; i += 1) {
for (let j = 0; j < copia.length - 1; j += 1) {
if (copia[j] > copia[j + 1]) {
const temp = copia[j];
copia[j] = copia[j + 1];
copia[j + 1] = temp;
}
}
}
return copia;
}
temp guarda um lado da troca. Sem ele, um valor se perde. Recarregue. As seis linhas devem dizer “passou”.
Erro comum: devolver a lista original sem copiar e ainda assim “passar” neste teste curto. No hábito profissional você copia. Faça isso agora.
Atividades
- Por que
funcoes.jscarrega antes detestes.js? - O que a página mostra se
dobrar(4)devolver 4? - Na bolha, para que serve a variável
temp? - Esvazie só
maiore recarregue. Qual mensagem aparece na terceira linha?
Respostas comentadas
- Os testes chamam as funções pelo nome. Se
testes.jsrodar primeiro,somarainda não existe e o corredor quebra inteiro. - A segunda linha fica vermelha: obtido 4, esperado 8. As outras dependem de você ter preenchido as funções.
- Guarda
copia[j]enquanto o vizinho ocupa o lugar. Depois o valor guardado vai para a posição da direita. - Algo como
falhou: obtido undefined / esperado 9, se a função não tiverreturn. Leia a mensagem; ela diz o combinado.
Referências
O arquivo completo
Referência do exemplo 18-testes, reproduzida aqui para que você possa conferir sem sair da página.
index.html
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1" name="viewport"/>
<title>Testes</title>
<link href="lab.css" rel="stylesheet"/>
<style>body{overflow-wrap:anywhere}img,input,textarea,select,iframe{max-width:100%}img{height:auto}fieldset,.cartao{min-width:0}pre{max-width:100%;overflow:auto}:focus-visible{outline:3px solid #005fcc;outline-offset:3px}.atalho-conteudo{position:absolute;left:.5rem;top:-6rem;background:white;color:#172f50;padding:.5rem;z-index:999}.atalho-conteudo:focus{top:.5rem}@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;transition:none!important;scroll-behavior:auto!important}}</style></head>
<body><a class="atalho-conteudo" href="#conteudo">Pular para o conteúdo</a><main id="conteudo" tabindex="-1">
<h1>Faça os testes passarem</h1>
<p>Edite <code>funcoes.js</code>. Não comece mudando <code>testes.js</code>.</p>
<ol id="resultado"></ol>
</main><script src="funcoes.js"></script><script src="testes.js"></script></body>
</html>
script.js
// este arquivo não é usado; veja funcoes.js