Palestra sobre Testes automatizados de Javascript com Jasmine realizada no primeiro ciclo do Plano de Geração de Conhecimento realizado em outubro de 2013, no LEMAF - Universidade Federal de Lavras.
2. Citações
“Teste de programa pode ser usado para mostrar a presença de erros,
mas nunca para mostrar a sua ausência.”
Edsger W. Dijkstra
“Sempre que você se sentir tentado a escrever algo em uma declaração
impressa ou uma expressão depurador, escrevê-lo como um teste de
vez.” Martin Fowler
"Qualquer recurso do programa sem um teste automatizado
simplesmente não existe.“
Kent Beck
3. Jasmine
• Jasmine é um framework de desenvolvimento orientado por
comportamento (BDD) para testes de Javascript. Ele não
depende de nenhum outro framework de Javascript, nem
mesmo requer um DOM (Document Object Model). E possui
uma sintaxe óbvia e limpa para escrever testes facilmente.
“http://pivotal.github.io/jasmine/”
5. SpecRunner.html
<!DOCTYPE ...>
<html>
<head>
<title>Jasmine Spec Runner</title>
<link rel="shortcut icon" type="image/png" href="lib/jasmine-1.3.1/jasmine_favicon.png">
<link rel="stylesheet" type="text/css" href="lib/jasmine-1.3.1/jasmine.css">
<script type="text/javascript" src="lib/jasmine-1.3.1/jasmine.js"></script>
<script type="text/javascript" src="lib/jasmine-1.3.1/jasmine-html.js"></script>
<!-- include source files here... -->
Arquivos fonte incluídos aqui
<!-- include spec files here... -->
Arquivos de teste incluídos aqui
<Código do Jasmine para execução e criação do relatório de testes>
6. Estrutura dos testes
Os testes são estruturados da seguinte maneira:
• Suite: Agrupa um conjunto de testes
• Spec: Descreve um caso de teste
• Expectation: Descreve um retorno esperado dentro de um
teste
7. Exemplo no Jasmine
describe("Primeiro agrupamento de testes", function () {
it("Descricao do primeiro teste.", function () {
Expectation
expect(true).toBeTruthy();
});
Spec
it("Descricao do segundo teste.", function () {
Expectation
expect(false).not.toBeTruthy();
Expectation
expect(1+1).toEqual(2);
});
});
Spec
Suite
9. Especificações são funções
describe(“Um agrupamento é uma função", function() {
var a,
b;
it(“assim como uma especificação", function() {
a = true;
b = 1 + 2 + 3;
expect(a).toBe(true);
expect(b).toBeGreaterThan(5);
});
});
11. Setup e Teardown
describe("A spec (with setup and tear-down)", function() {
var foo;
beforeEach(function() {
foo = 0;
foo += 1;
});
afterEach(function() {
foo = 0;
});
it("is just a function, so it can contain any code", function() {
expect(foo).toEqual(1);
foo = foo + 5;
});
it("can have more than one expectation", function() {
expect(foo).toEqual(1);
expect(true).toEqual(true);
});
});
12. Spies
describe("A spy", function() {
var foo,
bar = null;
beforeEach(function() {
foo = {
setBar: function(value) { bar = value; }
};
spyOn(foo, 'setBar');
foo.setBar(123);
foo.setBar(456, 'another param');
});
it("tracks that the spy was called", function() {
expect(foo.setBar).toHaveBeenCalled();
});
it("tracks its number of calls", function() {
expect(foo.setBar.calls.length).toEqual(2);
});
});
13. Proposta de trabalho
• Implementar um hipotético cadastro de currículos que fará
validações de preenchimento de campos obrigatórios.
• Implementar testes automatizados para as classes
envolvidas.
18. Especificações de testes
• CurriculoSpec – Para testes da classe
Curriculo
• EnderecoSpec – Para testes da classe
Endereco
• HabilidadeSpec – Para testes da classe
Habilidade
• PessoaSpec – Para testes da classe Pessoa
• UtilsSpec – Para testes da classe Utils
19. Exemplo de especificação
describe("Utils ", function(){
it("deve validar corretamente um cpf correto", function(){
expect(Utils.validarCPF("05969548677")).toBeTruthy();
});
it("deve validar corretamente um cpf incorreto", function(){
expect(Utils.validarCPF("05969548678")).toBeFalsy();
});
it("deve validar corretamente um inteiro (1) valido", function(){
expect(Utils.validarInt(1)).toBeTruthy();
});
it("deve validar corretamente um caracter inteiro ('1') valido", function(){
expect(Utils.validarInt('1')).toBeTruthy();
});
it("deve validar corretamente um caracter nao inteiro ('m')", function(){
expect(Utils.validarInt('m')).toBeFalsy();
});
it("deve validar corretamente um cep correto", function(){
expect(Utils.validarCep("37.200-000")).toBeTruthy();
});
it("deve validar corretamente um cep incorreto", function(){
expect(Utils.validarCep("37200-000")).toBeFalsy();
});
});
21. Jasmine-jQuery
Jasmine-jQuery oferece duas extensões para o framework
de teste para JavaSript, o Jasmine:
• um conjunto de matchers personalizados para framework jQuery
• uma API para lidar com HTML, CSS, JSON e fixtures em suas
especificações.
“https://github.com/velesin/jasmine-jquery”
22. Arquivo do framework
• jasmim-jquery.js
• Download: https://raw.github.com/velesin/jasminejquery/master/lib/jasmine-jquery.js
24. Exemplo de especificação
describe("Interface Cadastro de Currículo ", function () {
beforeEach(function () {
jasmine.getFixtures().fixturesPath = ".";
loadFixtures("cadastroCurriculo.html");
});
it("deve exibir campo de ajuda se nome for deixado em branco", function () {
var campoNome = document.getElementById("idNome"),
campoSobrenome = document.getElementById("idSobrenome");
campoNome.focus();
campoSobrenome.focus();
expect($("#idAjudaCampoNome").text()).toEqual("Os campos nome e
sobrenome são obrigatórios");
});