Relatório de cobertura de testes unitários com Angular e JEST
O objetivo deste artigo é mostrar como podemos gerar um relatório de cobertura de testes em um projeto Angular
Criando o projeto
O primeiro passo é criar o projeto e executá-lo para se certificar de que tudo está bem configurado:
ng new relatorio-cobertura
cd relatorio-cobertura/
ng serve
Se tudo correu bem você deverá ver algo como a imagem abaixo quando acessar o seguinte endereço http://localhost:4200 no seu navegador:

Removendo as dependências
Por padrão os projetos em Angular vêm com o Karma instalado. Como não vamos utilizá-lo, podemos removê-lo através do comando abaixo:
npm remove karma karma-chrome-launcher karma-coverage-istanbul-reporter karma-jasmine karma-jasmine-html-reporter
Os arquivos abaixo também podem ser removidos:
- /karma.conf.js
- /src/test.ts
Instalando e configurando JEST
Para instalar as dependências utilize o comando abaixo:
npm i -D jest @types/jest @angular-builders/jest
Abra o arquivo /tsconfig.spec.json e efetue as seguintes alterações:
- Substitua o texto
jasmineporjest - Remova a referência ao
test.ts
O arquivo ficará da seguinte forma:
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": [
"jest",
"node"
]
},
"files": [
"src/polyfills.ts"
],
"include": [
"src/**/*.spec.ts",
"src/**/*.d.ts"
]
}
No arquivo /tsconfig.json adicione o valor jest na propriedade "types" conforme o exemplo abaixo:
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"module": "esnext",
"moduleResolution": "node",
"importHelpers": true,
"target": "es2015",
"lib": [
"es2018",
"dom"
],
"types": [
"jest"
]
},
"angularCompilerOptions": {
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true
},
}
Por fim abra o arquivo /angular.json e troque a linha "builder": "@angular-devkit/build-angular:karma" por "builder": "@angular-builders/jest:run"
Execute o comando ng test e o resultado será:

Observação: quando criamos o projeto na primeira etapa, automaticamente o Angular cria um teste unitário src/app/app.component.spec.ts.
Relatório de cobertura
Para habilitar o relatório de cobertura, abra o arquivo /angular.json e adicione a propriedade "coverage": true conforme a seguinte imagem:

Execute novamente o comando ng test. Após executá-lo, será criada uma pasta chamada /coveragena raíz do seu projeto. Abrindo o arquivo /coverage/lcov-report/index.html é possível visualizar a cobertura dos testes:

Para testarmos a cobertura, vamos criar uma nova função, meuTeste(), dentro do arquivo /app.component.ts:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'relatorio-cobertura';
meuTeste() {
this.title = 'consolelog.com.br';
}
}
Ao executar novamente o teste, ng test, veja que o relatório aponta uma porcentagem menor (85.71%):

Clicando no link app.component.ts é possível visualizar quais trechos do código do componente que não foram cobertos pelos testes unitários:

Aumentando a cobertura
Para cobrir este trecho de código (método meuTeste()) será necessário editar o arquivo /app.component.spec.ts e adicionar um novo teste:
/* ... trecho acima ocultado ... */
it('deve trocar o title quando meuTeste() for chamado', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
fixture.componentInstance.meuTeste();
const app = fixture.componentInstance;
expect(app.title).toEqual('consolelog.com.br');
});
Veja que ao chamar o método meuTeste(), espera-se que o valor to title seja alterado para 'consolelog.com.br'. É justamente esta validação que nosso teste unitário efetua.
Ao executar novamente o comando ng test podemos ver que o novo trecho de código foi 100% coberto pelo novo teste unitário:

Considerações
A construção dos testes unitários é bem trabalhosa. Exige conhecimento, prática e tempo. Uma das grandes vantagens da construção dos testes unitários é que quem os constrói, precisa ter plena consciência da lógica empregada. Esta consciência permite uma eventual refatoração e/ou otimização de alguns trechos de código.