Desenvolvimento

3 mai, 2018

JavaScript: testes com Jasmine – Parte 01

Publicidade

Todo desenvolvedor sabe que o teste é uma das partes fundamentais no desenvolvimento de software, mas infelizmente nem sempre é possível implementar ele no seu dia a dia.

Depois de um tempo lendo alguns artigos e postagens em fóruns, notei que na maioria das vezes o pessoal pula a parte do teste por falta de tempo, mas acaba precisando desse tempo “economizado”, no meio ou no final do projeto para corrigir algo que o teste pegaria facilmente.

Um outro problema que eu notei, é que o pessoal tem utilizado o console.log() para analisar/validar o seu código em desenvolvimento e em alguns momentos para ajudar a corrigir algo que já está em produção. Abaixo, você pode ver um exemplo de um teste com o console.log() retirado da WEB.

Até ai tudo bem, né? Esse só foi um simples com o console.log(), mas e se você encontrasse algo como na imagem abaixo?

returno de validação com console.log()

Esse é um dos problemas de se testar o código com o console.log(). Esses exemplos acima estão simples, mas pesquisando pela WEB você pode encontrar algo como: “vai funcionar”, “graças a Deus foi”, “ajuda, Senhor”, e por aí vai.

Sei que um usuário comum não acessa o console do navegador para analisar código, mas e pensando em uma manutenção? Ou em uma nova funcionalidade no sistema? Acredito que dessa forma, além do código ficar difícil de se depurar, ainda existe uma grande chance de criar alguns problemas futuros (bugs).

Pensando nisso, eu resolvi estudar o Jasmine e criar uma série de artigos demonstrando como automatizar os seus testes com ele.

Jasmine

Em um breve resumo, o Jasmine é uma biblioteca de testes JavaScript que tem suporte ao BDD (Behaviour Driven Development). Ele é utilizado junto com o (TDD) Test Driven Development. Para facilitar o seu entendimento, vamos criar um exemplo:

function helloWorld() {
  return 'Hello world!';
}

Acima você tem uma function chamada helloWorld retornando uma string. No seu dia a dia você irá criar algo mais complexo, mas para o primeiro exemplo, veja como testar essa function.

describe('Ola Mundo', () => { 
  it('testar retorno da funcao ola mundo', () => { 
    expect(helloWorld()).toEqual('Hello world!'); 
  });
});

Como você pode notar no exemplo anterior, para testar algo com Jasmine, você pode utilizar: describe, it e expect. Abaixo, você tem uma breve descrição de cada um deles:

  • describe(string, function): nome do escopo do teste
  • it(string, function): nome do teste
  • expect(actual): chamada do evento/function … etc que será testado

No exemplo anterior eu utilizei o toEqual para validar se o retorno era o esperado, mas existem outros tipos que você pode utilizar para validar os seus testes. Veja na lista abaixo alguns dos retornos default do Jasmine, que você pode implementar no seu código.

expect(array).toContain(member);
expect(fn).toThrow(string);
expect(fn).toThrowError(string);
expect(instance).toBe(instance);
expect(mixed).toBeDefined();
expect(mixed).toBeFalsy();
expect(mixed).toBeNull();
expect(mixed).toBeTruthy();
expect(mixed).toBeUndefined();
expect(mixed).toEqual(mixed);
expect(mixed).toMatch(pattern);
expect(number).toBeCloseTo(number, decimalPlaces);
expect(number).toBeGreaterThan(number);
expect(number).toBeLessThan(number);
expect(number).toBeNaN();
expect(spy).toHaveBeenCalled();
expect(spy).toHaveBeenCalledTimes(number);
expect(spy).toHaveBeenCalledWith(...arguments);

Automatizando testes

Para que você possa criar os seus testes com Jasmine depois de terminar de ler esse artigo, quer um exemplo real mais próximo do nosso dia a dia?

Bom, imagine o seguinte cenário: você precisa criar um método que valide se um usuário tem a idade mínima para acessar um conteúdo X, precisa desenvolver algo que possa ser chamado de qualquer lugar do sistema e que valide se esse usuário tem permissão para acessar esse conteúdo com base na sua data de nascimento. Para melhorar o nosso caso de teste, nós precisamos atender todas as classificações indicativas da imagem abaixo:

Para criar esse teste, eu irei utilizar o VS Code (Visual Studio Code) e a biblioteca do Jasmine que você pode encontrar no seguinte link: Jasmine. Baixe ele no seu computador, em seguida descompacte o arquivo .zip e abra o código no seu VS Code. Abaixo você tem uma imagem demonstrando esse passo:

VS Code

Analisando o código acima, você tem:

  • lib: diretório com as bibliotecas do Jasmine
  • spec: diretório para criação dos testes
  • src: diretório contendo as classes de negócio

O próximo passo será criar o código responsável por validar o cenário de teste descrito acima. Para isso, crie os arquivos abaixo dentro do seu projeto no VS Code:

./src/ClassificacaoIndicativa.js

function ClassificacaoIndicativa() {
  var valida = {

    valida_classificacao_indicativa: function(livre, data_nascimento, idade) {
      if (livre) {
        return true;
      } else {
        let birthday = data_nascimento.split("/");
        let day = Number(birthday[1]);
        let month = Number(birthday[0]);
        let year = Number(birthday[2]);
        return new Date(year + idade, month - 1, day) <= new Date();
      }
    }

  return valida;
}

./spec/ClassificacaoIndicativaSpec.js

describe("Classificacao indicativa", function() {
  
  beforeEach(function() {
    classificacao = new ClassificacaoIndicativa();
  });

  it("Classificacao maior de 18 anos", function() {
    expect(classificacao.valida_classificacao_indicativa(false,"05/04/1985",18)).toMatch(true);
  });

});

Agora, para validar os outros métodos você pode utilizar os parâmetros:

  • livre: para indicar que o conteúdo pode ser visto por todos
  • data de nascimento: para passar a idade do usuário
  • idade: que o usuário precisa ter para acessar esse conteúdo

Veja abaixo um cenário validando todos os requisitos do nosso teste:

describe("Classificacao indicativa", function() {
  beforeEach(function() {
    classificacao = new ClassificacaoIndicativa();
  });

  describe("Classificacao live", function() {
    it("tem que permitir todos", function() {
      expect(
        classificacao.valida_classificacao_indicativa(true, "05/04/1985", 100)
      ).toMatch(true);
    });
  });

 describe("Classificacao de 10 anos", function() {

    it("usuario tem a idade minima para 10 anos", function() {
      expect(
        classificacao.valida_classificacao_indicativa(true, "05/04/2008", 10)
      ).toMatch(true);
    });

    it("usuario não tem a idade minima para 10 anos", function() {
      expect(
        classificacao.valida_classificacao_indicativa(false, "05/04/2018", 10)
      ).toMatch(false);
    });
  });


  describe("Classificacao de 12 anos", function() {

    it("usuario tem a idade minima para 12 anos", function() {
      expect(
        classificacao.valida_classificacao_indicativa(true, "05/04/2006", 12)
      ).toMatch(true);
    });

    it("usuario não tem a idade minima para 12 anos", function() {
      expect(
        classificacao.valida_classificacao_indicativa(false, "05/04/2013", 12)
      ).toMatch(false);
    });
  });

  describe("Classificacao de 14 anos", function() {

    it("usuario tem a idade minima para 14 anos", function() {
      expect(
        classificacao.valida_classificacao_indicativa(true, "05/04/2004", 14)
      ).toMatch(true);
    });

    it("usuario não tem a idade minima para 14 anos", function() {
      expect(
        classificacao.valida_classificacao_indicativa(false, "05/04/2013", 14)
      ).toMatch(false);
    });
  });

  describe("Classificacao de 16 anos", function() {

    it("usuario tem a idade minima para 16 anos", function() {
      expect(
        classificacao.valida_classificacao_indicativa(true, "05/04/2002", 16)
      ).toMatch(true);
    });

    it("usuario não tem a idade minima para 16 anos", function() {
      expect(
        classificacao.valida_classificacao_indicativa(false, "05/04/2013", 16)
      ).toMatch(false);
    });
  });

  describe("Classificacao de 18 anos", function() {

    it("usuario tem a idade minima para 18 anos", function() {
      expect(
        classificacao.valida_classificacao_indicativa(true, "05/04/2000", 18)
      ).toMatch(true);
    });

    it("usuario não tem a idade minima para 18 anos", function() {
      expect(
        classificacao.valida_classificacao_indicativa(false, "05/04/2013", 18)
      ).toMatch(false);
    });
  });
});

Agora, para executar e validar o teste, eu irei utilizar um plugin do VS Code chamado live serve, mas caso não tenha ele ou não esteja utilizando o VS Code, você pode subir o seu código no IIS ou em um outro servidor WEB.

Com o live server sendo executado no meu VS Code, veja abaixo uma imagem demonstrando o status dos testes desenvolvidos no passo anterior:

Bem simples, né?

Para finalizar esse artigo, pense no pior cenário possível: você precisa implementar uma nova funcionalidade em um código legado, quem desenvolveu não está mais na empresa, e o melhor, até o final do seu expediente – algo sem pressão.

Um cenário como esse do nosso exemplo com a classificação indicativa iria ou não te deixar mais confortável para aceitar essa tarefa? Com isso finalizamos a primeira parte dessa série sobre Jasmine. Espero ter ajudado e até um próximo artigo, pessoal!