Não faça testes, faça specs!

Alura
lacerdaph
lacerdaph

Compartilhe

Avalie este artigo

7 minutos de leitura

Como foi difícil escrever este artigo, ou melhor, esta série que iremos lançar. Eu sou desenvolvedor Java, demorei anos para entender todo parte do ecossistema que envolve a plataforma, o que cada framework faz, como é sua arquitetura, onde e como deveria ser usado e como googlar determinado problema. Lembro até hoje a alegria que tive ao configurar um projeto Struts + JPA usando Maven (até que enfim tinha entendido esse tal de gerenciador de dependências).

Enfim, você não sabe o quanto eu caminhei para chegar até aqui, para simplesmente ....... ter que reaprender tudo de novo!!! É isso mesmo amigos, bem-vindo ao maravilhoso reino encantando do JavaScript.

Curto e grosso amigo desenvolvedor: você tem um monte de nomes para aprender desse novo mundo, muitos nomes (node, npm, gulp, grunt, jasmine, typescript, react, webpack, babel, expressjs, bower, ...). É o tal do mundo front-end! E pode ter certeza que amanhã haverá mais frameworks / bibliotecas.

Para essa série, chamei Tiago Lage para ser coautor, que já estava nesse mundo antes de ser modinha e tentava, sem sucesso (por culpa minha), explicar-me features legais do javascript como hoisting.

Depois de um tempo batalhando lado a lado com frameworks para desenvolver algo minimamente decente, descobri que o mais importante disso tudo não é o que está no meu src/main/java, mas sim o que está no src/test/java. O seu código está ruim? Tem testes? Ok, depois alguém refatora. Mas não deixe de fazer testes!!! Aliás, a não ser que você trabalhe no StackOverflow e tenha usuários working for free legais que forneçam feedback exclusivo!

E como lidar com testes especificações em JavaScript? Bom, durante a série de artigos iremos testar diferentes códigos javascript e frameworks (jQuery, Vue, Angular), obtendo cobertura de código, usando mocks em funções e até mesmo no html. Vamos ver até onde isso vai....

Entendendo as especificações

Imagine por um momento que você está trabalhando em um projeto que teve a especificação perfeita, ou seja, todos os comportamentos esperados do sistema estão detalhadamente descritos, cada regra de negócio, cada input válido ou inválido, cada tela e mensagem de erro. Imaginou? Agora imagine que o computador possa entender essa especificação "perfeita". Poderíamos dizer então que se o computador pudesse validar todas estas especificações, então nosso sistema está correto, não é mesmo?

Essa modinha tendência começou a se difundir com o Ruby e o framework RSpec que prometia trazer o Behaviour Driven Development (Desenvolvimento Guiado por Comportamento) para o Ruby.

Entretanto, como todos sabem, os requisitos nunca são perfeitos e também não são escritos em uma linguagem de máquina. Portanto, o que podemos fazer para que essa estratégia funcione? Bom, podemos pegar os requisitos "reais" (descritos em um documento em linguagem de negócios), aperfeiçoá-los e traduzí-los para uma linguagem de máquina. A boa notícia é que grande parte do ferramental já existe na maioria das linguagens.

Bom, mas o que se ganho com toda essa trabalheira? Ela irá permitir utilizar Test Driven Development  - TDD (Desenvolvimento guiado por testes). Desse modo, nosso projeto real começa com todos os testes falhando, à medida que desenvolvemos suas funcionalidades, os testes começam a passar. Assim, quando todos os testes estiverem passando, dizemos que nosso projeto está completo.

Banner de aniversário da Alura com mensagem sobre evolução de carreira em tecnologia. A imagem destaca a oportunidade de estudar e crescer profissionalmente com cursos online, com botão “Aproveite” para acessar a plataforma e desenvolver habilidades tech.

First things first

A primeira atitude que precisamos tomar para começar a fazer testes em JavaScript é escolher um Framework. O mundo Java se divide em Team JUnit e Team TestNG. Há uma boa comparação aqui. No mundo JavaScript, a briga maior é entre o Team Jasmine e o Team Mocha.js (boa comparação aqui também). Desconsiderando as diferenças óbvias de linguagem, há também uma grande diferença conceitual na forma de abordagem dos testes entre o pessoal do Java e o pessoal do JavaScript. No mundo Java, em geral, os frameworks de testes seguem mais a filosofia do teste unitário de unidade, e no mundo JavaScript é mais comum a terminologia do Behavior Driven Design (BDD).

Segue exemplo de teste em Java (JUnit4). Veja que utilizamos anotações sobre os métodos para definir qual a função dos mesmos no ciclo de vida do nosso teste:

Suite de testes - AllTests:

https://github.com/tiagolpadua/MinhaCalculadoraJava

 import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class) @SuiteClasses({ CalculadoraTest.class }) public class AllTests { } 

Casos de teste - CalculadoraTest:

 import static org.junit.Assert.assertEquals; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test;
public class CalculadoraTest {
@BeforeClass public static void runOnceBeforeClass() { System.out.println("@BeforeClass- executa uma vez antes de todos testes"); }
@AfterClass public static void runOnceAfterClass() { System.out.println("@AfterClass - executa uma vez após todos testes"); }
@Before public void runBeforeTestMethod() { System.out.println("@Before - executa antes de cada teste"); }
@After public void runAfterTestMethod() { System.out.println("@After - executa após cada teste"); }
@Test public void testSoma() { Calculadora calculadora = new Calculadora(); assertEquals(3, calculadora.somar(2, 1)); System.out.println("@Test - testSoma"); }
@Test public void testIncremento() { System.out.println("@Test - testIncremento"); Calculadora calculadora = new Calculadora(); assertEquals(3, calculadora.incrementar(2)); } } 

Bom, mas isso aí talvez você já saiba de cor e salteado, mas e como é no mundo JavaScript?

O JavaScript não tem o recurso de anotações como o Java, nesse caso, segue o exemplo abaixo em JavaScript utilizando o framework Jasmine, que disponibiliza algumas funções para controlar o ciclo de vida dos testes e asserções sobre os resultados:

 describe('Calculadora', function () {
beforeAll(function () { console.log('beforeAll - executa uma vez antes de todos testes'); });
afterAll(function () { console.log('afterAll - executa uma vez após todos testes'); });
beforeEach(function () { console.log('beforeEach - executa antes de cada teste'); });
afterEach(function () { console.log('afterEach - executa após cada teste'); });
it('Deve somar os números', function () { console.log('teste calc.somar'); var calc = new Calculadora(); expect(calc.somar(2, 1)).toBe(3); });
it('Deve incrementar um número', function () { console.log('teste calc.incrementar'); var calc = new Calculadora(); expect(calc.incrementar(2)).toBe(3); }); }); 

No fim as funcionalidades são muito parecidas. Vamos fazer um paralelo dos métodos entre os mundos do Java e do JavaScript pra ficar mais claro:

Java (JUnit)

JavaScript (Jasmine)

Suite

describe

BeforeClass

beforeAll

AfterClass

afterAll

Before

beforeEach

After

afterEach

test

it

assert

expect

 

O que vem por aí

Finalizando, este foi o primeiro artigo de uma série bem bacana que estamos elaborando (for dummies and ninjas). Nos próximos artigos falaremos sobre Karma, PhantomJS, Matchers, testes de unidade, integração e sistema, e até mesmo, como testar seu HTML que ainda nem existe. Também abordaremos testes mais complexos envolvendo o conceito de Mocks e Spys.

Por fim, falaremos sobre como medir cobertura de código e como integrar todo esse ferramental no build da sua aplicação em um servidor de integração contínua com a ajuda de Gulp e Grunt. Se você é iniciante como eu ou ninja como o Tiago, comenta sua experiência nesse mundo complicado desafiador JavaScript. Ademais, você também pode acompanhar o código que estamos elaborando para os próximos posts no meu GitHub. Comenta aí!

Avalie este artigo

Veja outros artigos sobre Inovação & Gestão