Guia – Jasmine uma breve introdução aos seus conceitos.
Compartilhe este conteúdo:
O Jasmine é um framework de teste JavaScript de código aberto lançado em 14 de setembro de 2010. Desde então, ele se tornou amplamente conhecido pela sua usabilidade, facilidade na implementação de testes automatizados e pela integração eficaz com o Angular.
Bom, o foco deste artigo é uma breve introdução ao Jasmine, bom, vamos lá. 🏎️🏎️
Em primeiro plano precisamos implementar o Jasmine em um projeto Javascript, inclusive temos um artigo sobre, clique aqui.
Após a instalação, nos deparamos com um cenário completamente novo. Contudo, não se preocupe, pois vamos guiar você através de cada passo.
Antes de escrever qualquer teste vamos entender o procedimento de testes, o Jasmine utiliza o Behavior Driven Development (BDD), nesse procedimento os testes são descritos de forma clara e natural para refletir o comportamento esperado do software.
Um exemplo de um BDD 👇
Funcionalidade: Calculadora
Cenário: Somar dois números
Dado que eu tenho uma calculadora
Quando eu somo 2 e 2
Então o resultado deve ser 4
Cenário: Subtrair dois números
Dado que eu tenho uma calculadora
Quando eu subtraio 2 de 2
Então o resultado deve ser 0
Agora que entendemos sobre o procedimento de teste utilizado pelo Jasmine, vamos mergulhar ainda mais fundo.
Ao inicializar o Jasmine nos deparamos com uma pasta nomeada "
.spec
"
A pasta "
é comumente utilizada para organizar e armazenar os arquivos de testes de especificação.spec
"
🤔 O que é spec afinal ?
Em BDD, as especificações (specs) descrevem o comportamento que o sistema deve exibir em determinadas circunstâncias.
Os testes unitários escritos usando uma abordagem “spec
“ tendem a ser mais legíveis e orientados para o comportamento do sistema, em contraste com os testes mais tradicionais que focam na estrutura interna do código. Especificamente, no contexto de BDD:
- Specs (Especificação): Descrevem o comportamento esperado do sistema em termos de exemplos claros e compreensíveis.
Portanto, “spec
” em testes unitários refere-se à prática de descrever o comportamento do sistema de forma clara e compreensível, focando nos resultados esperados e na interação com o sistema, em vez de detalhes internos de implementação.
📛 Convenções de Nomenclatura
Quando criamos um arquivo de testes no Jasmine devemos seguir o padrão nome ponto spec ponto js (extensão) exemplo:
qualquernome
.
spec
.
js
O sufixo ".spec.js
” é uma convenção de nomenclatura usada para indicar que o arquivo contém testes de especificação para o código. Essa nomenclatura ajuda a identificar rapidamente quais arquivos são responsáveis pelos testes e quais são os arquivos de código de implementação.
Entretanto, essa convenção de nomenclatura não está escrita em ferro e fogo, ela é adaptável as necessidades, podemos adicionar ou remover nomenclaturas, O arquivo jasmine.json é responsável por gerenciar quais arquivos o Jasmine vai ler, isso permite uma melhor organização e personalização.
🧐 Analisando o jasmine.json
Já sabemos que o jasmine.json gerencia quais arquivos o Jasmine vai ler. Neste tópico iremos explora detalhadamente cada propriedade dessa configuração.
Dentro da pasta support podemos observar o arquivo jasmine.json, vamos abrir e analisa-lo minuciosamente
spec_dir
: Define o diretório base onde os arquivos de especificações (testes) estão localizados.
- Exemplo:
"spec"
significa que os testes estão na pastaspec
.
spec_files
: Especifica um array de padrões glob para localizar os arquivos de testes.
- Exemplo:
"**/*[sS]pec.?(m)js"
procura por qualquer arquivo cujo nome termina com “Spec.js” ou “spec.js”, e opcionalmente pode terminar com “Spec.mjs” ou “spec.mjs”, em qualquer subdiretório
helpers
: Define um array de padrões glob para localizar os arquivos de helpers. Helpers são scripts que contêm código de configuração ou utilidades que ajudam nos testes, mas que não são testes em si.
- Exemplo:
"helpers/**/*.?(m)js"
procura por todos os arquivos JavaScript (e módulos JavaScript) na pastahelpers
e suas subpastas.
env
: Contém configurações específicas do ambiente de execução dos testes.
stopSpecOnExpectationFailure
: Um booleano que, se definido comotrue
, faz com que o Jasmine pare a execução do teste assim que uma expectativa falhar dentro de um teste (spec). Se definido comofalse
, todos os testes serão executados independentemente das falhas.- Exemplo:
"stopSpecOnExpectationFailure": false
permite que todos os testes sejam executados, mesmo se alguns falharem.
- Exemplo:
random
: Um booleano que, se definido comotrue
, faz com que os testes sejam executados em ordem aleatória. Isso ajuda a identificar dependências entre testes que podem causar falhas intermitentes.- Exemplo:
"random": true
faz com que a ordem dos testes seja aleatória a cada execução.
- Exemplo:
Em resumo:
spec_dir
: Local onde procurar os testes.
spec_files
: arquivos considerados como testes.
helpers
: define scripts auxiliares que configuram ou ajudam os testes.
env
: define configurações do ambiente de teste, como o comportamento em caso de falhas e a ordem de execução dos testes.
🆕 Nova convenção de nomenclatura
Pode acontecer de você querer padronizar o seu projeto ou seguir uma cartela de nomenclaturas, seria interessante criar uma nova convenção de nomenclatura no Jasmine para seguir esse padrão.
Para adicionar uma nova convenção de nomenclatura, precisamos seguir o padrão glob, vamos adicionar a palavra teste por exemplo como um novo padrão
Explicação do Novo Padrão
**/*[tT]este.?(m)js
:**/
: Permite qualquer número de diretórios e subdiretórios.*[tT]este.
: Captura qualquer sequência de caracteres antes da parte “teste” (com “t” maiúsculo ou minúsculo) seguida de um ponto.?(m)
: Torna a letra “m” opcional, permitindo tanto “.js” quanto “.mjs”.js
: Captura a extensão “.js”.
Novo padrão estabelecido, juntamente com o padrão spec:
Com este novo padrão estabelecido, agora o Jasmine consegue ler arquivos com a convenção de nomenclatura teste por exemplo:
login.teste.js
Neste tipo de abordagem podemos organizar melhor a nossa estrutura e dar mais legibilidade caso precise.
🧪 Hora dos testes!
Chegou a hora de fazermos os testes unitários. Para iniciar um teste, precisamos de um proposito claro, como vimos anteriormente o Jasmine utiliza o procedimento BDD, que nos permite descrever qual funcionalidade estamos testando.
Se lembra do nosso exemplo de BDD no inicio do artigo? então, iremos implementa-lo para entendermos a dinâmica, escrita no BDD e a implementação de teste.
Ao escrever um teste no Jasmine, cada caso de teste é definido com o método it
.
O método it
é uma função que descreve um comportamento específico que o código deve ter e contém a lógica necessária para verificar esse comportamento.
Parâmetros do Método it
O método it
no Jasmine recebe dois parâmetros principais:
- Descrição (description): Uma string que descreve o comportamento esperado que está sendo testado.
- Função de Teste (test function): Uma função que contém o código que realiza o teste, incluindo as expectativas (assertions) necessárias para verificar o comportamento esperado.
1. Descrição (description)
- Tipo: String
- Propósito: Fornecer uma descrição clara e concisa do comportamento ou funcionalidade que está sendo testada. Esta descrição é exibida quando os testes são executados, ajudando a identificar qual caso de teste está sendo validado e facilitando a leitura e manutenção dos testes.
- Exemplo:
'deve retornar 4 quando somar 2 e 2'
2. Função de Teste (test function)
- Tipo: Função
- Propósito: Contém o código que executa o teste. Dentro dessa função, você escreve as expectativas usando métodos como
expect
para verificar se o comportamento do código é o esperado.
Testando a calculadora.
Primeiro, vamos definir uma funções simples: soma
.
function soma(a, b){
return a+b
}
it(“Ao somar 2 + 2 resultado tem que ser 4”, function(){
const result = soma(2, 2);
expect(result).toBe(4)
})
Explicando o código:
- Criamos uma função de soma.
- Em seguida temos o método it para o teste de caso individual, note que no primeiro parâmetro, há uma breve descrição do caso o qual estamos testando, segundo parâmetro temos uma função de callback, dentro temos um variável que recebe o retorno da função soma que tem seus dois parâmetros com um valor, nesse caso colocamos 2.
- Note que dentro da função temos método expect e o matcher toBe.
Expect: é uma função utilizada para iniciar uma cadeia de asserções, ou seja, é usada para verificar se um valor atende a uma condição específica durante o teste.toBe
: é um dos matchers (correspondentes) disponíveis no Jasmine. Matchers são funções que são usadas apósexpect
para especificar o que esperamos do valor sendo testado. O matchertoBe
compara estritamente se dois valores são idênticos em tipo e valor (usando o operador===
em JavaScript).
Agora rodaremos o Jasmine com o comando npm test:
Nosso teste passou com 1 spec e 0 falhas, isso significa que nossa função passou na cobertura de teste prevista no BDD. Lembrando que quando estamos testando um código, devemos fazer uma boa cobertura de testes, nesse exemplo estamos fazendo um teste de resultado esperado, porém há diversos testes há serem implementados segue a lista de alguns que pode te ajudar a melhorar o seu projeto:
- Resultados Esperados
- Tratamento de Erros
- Limites e Extremidades
- Efeitos Colaterais
- Estados Internos
🔧 Melhorando o código de teste
Na medida que os testes de caso aumentam, se torna necessário uma boa organização. O describe
é um método no Jasmine que serve exatamente para agrupar testes relacionados, o que ajuda na organização e na legibilidade do código de teste.
Exemplo de uso com mais testes:
describe(“Testes da calculadora”, function(){
it(“deve somar números positivos corretamente”, function() {
const result = soma(2, 3);
expect(result).toBe(5);
});
it(“deve tratar soma com zero”, function() {
const result = soma(5, 0);
expect(result).toBe(5);
});
it(“deve lidar com números negativos”, function() {
const result = soma(-5, 3);
expect(result).toBe(-2);
});
})
Caso queira adicionar mais um describe para descrever ainda melhor o que cada teste de caso faz:
describe(“Testes da calculadora”, function(){
describe(“Operação de Soma”, function() {
it(“deve somar números positivos corretamente”, function() {
const result = soma(2, 3);
expect(result).toBe(5);
});
it(“deve tratar soma com zero”, function() {
const result = soma(5, 0);
expect(result).toBe(5);
});
it(“deve lidar com números negativos”, function() {
const result = soma(-5, 3);
expect(result).toBe(-2);
});
});
})
Benefícios da Organização com describe
- Clareza e Legibilidade: Facilita entender rapidamente quais funcionalidades ou operações estão sendo testadas.
- Facilidade de Manutenção: Ajuda na adição, remoção ou modificação de testes relacionados de forma organizada.
- Isolamento de Problemas: Caso ocorra um problema, você sabe exatamente onde procurar dentro do bloco
describe
específico.
🤼 Matchers Uma breve introdução
Matchers são métodos encadeados após expect
, e cada matcher específico define uma condição que o valor deve atender para que o teste passe
Matcher | Descrição | Exemplo |
---|---|---|
`.toBe(valorEsperado)` | Verifica se o valor é estritamente igual ao valor esperado. | `expect(2 + 2).toBe(4);` |
`.toEqual(valorEsperado)` | Verifica se o valor é igual ao valor esperado, realizando uma comparação profunda. | `expect({ foo: ‘bar’ }).toEqual({ foo: ‘bar’ });` |
`.toBeTruthy()` | Verifica se o valor é avaliado como verdadeiro. | `expect(true).toBeTruthy();` |
`.toBeFalsy()` | Verifica se o valor é avaliado como falso. | `expect(false).toBeFalsy();` |
`.toBeUndefined()` | Verifica se o valor é `undefined`. | `expect(undefined).toBeUndefined();` |
`.toBeNull()` | Verifica se o valor é `null`. | `expect(null).toBeNull();` |
`.toBeInstanceOf(construtor)` | Verifica se o valor é uma instância do construtor especificado. | `expect(new Error()).toBeInstanceOf(Error);` |
`.toContain(valor)` | Verifica se um array ou iterável contém o valor especificado. | `expect([1, 2, 3]).toContain(2);` |
`.toThrow(mensagemOuExpressaoRegular)` | Verifica se uma função lança uma exceção. | `expect(() => { throw new Error(‘Erro!’); }).toThrow(‘Erro!’);` |
🏁✅ Conclusão!
Espero que tenha gostado desse artigo, em breve traremos mais conteúdos sobre testes unitários.
Veja também:
Guia prático – teste unitário com Jasmine js no JavaScript : Clique aqui
Cypress ou Puppeteer? : Clique aqui
Deixe uma resposta