Algumas impressões sobre Mocha e Jest

Artigos - 12/Ago/2020 - por André Kanamura

Na Campus Code sempre ensinamos que a escrita de testes ajuda muito na rotina de desenvolvimento de software independente do nível de experiência das pessoas. Por essa razão, mesmo em treinamentos com iniciantes, usamos e estimulamos o pensamento guiado a escrever testes e usá-los como métrica para determinar a conclusão de uma tarefa. Nossa experiência majoritária é com Ruby on Rails, afinal o framework sempre incentivou o uso de testes e essa ideia foi abraçada pela comunidade.

Recentemente começamos a dedicar esforços e expandir esses conhecimentos para outras tecnologias, incluindo JavaScript. Nestes estudos escolhemos experimentar dois dos frameworks de testes mais utilizados atualmente: Mocha e Jest. A partir desses estudos, decidi relatar um pouco da experiência ao usar ambos frameworks.

Para o nosso contexto, algumas das qualidades mais relevantes são:

  • Facilidade de configuração;
  • Facilidade de implementar o código de testes;
  • Legibilidade do código de testes;
  • Clareza das mensagens de erro;

Não nos preocupamos, num primeiro momento, com a capacidade de fazer mocks. Assim, a presença da funcionalidade não influencia muito na nossa escolha, mas é provável que no seu caso isso seja diferente.

Antes de começar a falar sobre os resultados dos experimentos, vou mostrar um resumo sobre os dois frameworks.

Mocha

O framework Mocha existe desde 2011 e sempre se manteve entre os mais populares na comunidade. Ele roda com Node.js e possui uma grande quantidade de funcionalidades, o que faz dele um dos frameworks mais flexíveis. Uma ferramenta indispensável, na minha opinião, é uma biblioteca de asserções, como o Chai, por exemplo.

Pros Contras
Flexibilidade Não vem com biblioteca de asserção por padrão
Possui uma série de bibliotecas para adicionar funcionalidades Exige configuração para incorporar novas funcionalidades
Por ser um projeto mais maduro, existe grande quantidade de conteúdo de suporte disponível


Jest

O Jest foi criado pelo Facebook para trabalhar com React, mas ele também pode ser usado em projetos que utilizam Vue, Angular, entre outras ferramentas para JavaScript. Desde o seu lançamento em 2014, o projeto é Open-source. É um framework focado em simplicidade e facilidade de uso, vindo por padrão com uma série de funcionalidades integradas, com uma biblioteca de asserções e Snapshot Testing.

Pros Contras
Possui biblioteca de asserções e outras funcionalidades integradas Por ser um projeto mais recente, possui menor quantidade de ferramentas disponíveis


Comparações

Não cheguei a testar a fundo os frameworks, mas parece que a comunidade concorda que a principal vantagem do Jest é que ele vem pronto para atender quase todas as necessidades do seu projeto sem demandar configurações adicionais. Por outro lado, a maior vantagem do Mocha é também seu pior defeito: apesar da sua flexibilidade por possuir muitas bibliotecas para adicionar funcionalidades ao framework, ele demanda trabalho para configurar tudo conforme seu projeto exigir.

Ambos foram muito simples de instalar e começar a testar sem dificuldades, apenas consultando a documentação oficial. Talvez o Mocha tenha uma pequena vantagem com relação à disponibilidade de material de suporte por ser mais antigo, afinal um maior número de pessoas já teve a oportunidade de usá-lo e de produzir conteúdos a seu respeito ao longo dos anos. Mas o Jest parece estar crescendo bastante em popularidade e esse cenário deve mudar rapidamente.

Aqui acabam as semelhanças e vou falar um pouco sobre as principais diferenças que encontrei.

Os testes

Testes automatizados se tornaram parte indispensável em desenvolvimento de software, principalmente em grandes negócios nos quais a base código é o patrimônio da empresa, ou seja, onde qualquer falha pode causar prejuízos enormes. Por isso, é importante que um framework de testes nos permita, além executar todo tipo de teste, também criar testes de forma rápida e fácil. Caso contrário, pode ser muito tentador deixar os testes de lado e, em algum momento, parte da sua aplicação pode ficar desprotegida.

Nos dois frameworks é bastante simples o processo de implementação, bastando criar um arquivo, importar o código que queremos avaliar e escrever os testes. Cada teste começa com uma descrição do que será testado, seguida do bloco de código que será executado. Os frameworks tem formas diferente de fazer isso. Como o Jest possui uma biblioteca de asserção integrada, ele torna mais fácil escrever código JavaScript mais idiomático (no entanto no idioma inglês), ou seja, com melhor legibilidade. O Mocha permite instalar uma biblioteca de asserção, mas sem configurações adicionais seus testes têm menor legibilidade. Observe os exemplos abaixo, baseados em um dos desafios da plataforma Code Saga:

Mocha:

var assert = require('assert');
var Word = require('./word.js')

describe('Retornar a palavra mais longa em', function () {
  it('I have a bad feeling about this', function () {
    assert.equal(Word.longest("I have a bad feeling about this"), "feeling");
  });

  it('These are not the droids you are looking for', function () {
    assert.equal(Word.longest("These are not the droids you are looking for"), "looking");
  })
});

describe('Retornar a palavra mais curta em', function () {
  it('I find your lack of faith disturbing', function () {
    assert.equal(Word.shortest("I find your lack of faith disturbing"), "I");
  });

  it('May the force be with you', function () {
    assert.equal(Word.shortest("May the force be with you"), "be");
  })
});

Jest:

const Word = require('./word.js')

describe('Retornar a palavra mais longa em', () => {
  test('I have a bad feeling about this', () => {
    expect(Word.longest("I have a bad feeling about this")).toEqual("feeling");
  });

  test('These are not the droids you are looking for', () => {
    expect(Word.longest("These are not the droids you are looking for")).toEqual("looking");
  });
});

describe('Retornar a palavra mais curta em', () => {
  test('I find your lack of faith disturbing', () => {
    expect(Word.shortest("I find your lack of faith disturbing")).toEqual("I");
  });

  test('May the force be with you', () => {
    expect(Word.shortest("May the force be with you")).toEqual("be");
  });
});

No desafio queremos verificar se o método longest retorna a palavra mais longa da string passada como argumento e se o método shortest retorna a palavra mais curta. Por isso, incluímos as descrições "Retornar a palavra mais longa em" e "Retornar a palavra mais curta em", e dentro dos blocos descrições mais específicas para cada caso. Como sabemos exatamente o que podemos esperar da execução dos métodos, podemos executar o código Word.longest("String alvo") e incluir o que esperamos ser retornado. Você não precisa usar o bloco describe para agrupar testes se não quiser. No Jest essa linha fica:

expect(Word.longest("I have a bad feeling about this")).toEqual("feeling");

Note como é possível compreender com facilidade o objetivo do teste: "a expectativa é de que a execução do método com a string como argumento retorne um valor igual a palavra especificada". Já no framework Mocha, a linha não é tão fácil de ser lida:

assert.equal(Word.longest("I have a bad feeling about this"), "feeling");

Para tornar os testes do Mocha mais legíveis, podemos instalar alguma biblioteca de asserções adicional.

Levando em consideração nosso caso específico, é vantajoso que os testes tenham boa legibilidade, já que são direcionados para um público que em geral não tem o costume de usar frameworks de testes ou em alguns casos estão inclusive começando os estudos em programação.

Depois que estiverem prontos, podemos rodar os testes e avaliar os resultados.

Estrutura dos resultados dos testes

A forma como os testes são processados e os resultados são apresentados no terminal variam entre os frameworks. O Mocha executa os testes em série, enquanto o Jest, por padrão, roda em paralelo, mas é possível forçar a execução sequencial. Para fins de debug, executar os testes em série pode ser vantajoso, mas talvez em paralelo o desempenho seja melhor. Nos nossos experimentos, com uma pequena quantidade de testes, a velocidade de execução foi rápida em ambos os casos, mas o Jest pareceu atrasar a renderização dos resultados, talvez por conta da quantidade de informações que são apresentadas em tela. Observe nas imagens abaixo as diferenças na forma como os resultados são renderizados:

Mocha:

Jest:

O Jest apresenta maior quantidade de informações, incluindo uma parte do código onde ele detectou um problema. Os dois frameworks mostram as mensagens que configuramos para cada teste e o resultado de sua execução e a linha no código onde ocorreu falha na execução.

A forma como os resultados dos testes são apresentados pode influenciar a maneira como a pessoa que está programando encara o processo de resolução do desafio proposto. Neste quesito, apesar de ser mais completo, a quantidade de informações apresentadas pelo Jest pode ser um pouco intimidadora para um iniciante.

Outra característica importante para nossa comparação é a forma como os frameworks tratam erros mais severos que quebram a aplicação em tempo de execução. Apesar de ser mais crítico, para manter boa a legibilidade é importante que o framework consiga gerenciar o erro e manter o resultado razoavelmente claro e compacto durante a execução do teste. Neste aspecto o Mocha se demonstrou inferior ao Jest. Quando implementei a classe Word de forma incorreta, por exemplo, o seguinte foi apresentado:

Já o Jest continuou funcionando da maneira com deveria:

Além disso, apesar de ambos indicarem erro de sintaxe, o Jest sobe a mensagem Unexpected token, expected "(" (1:31), enquanto o Mocha sobe Unexpected token '{'. Ligeiramente diferentes, mas acho que o Jest é um pouco mais fácil de entender.

Considerações finais

A implementação de ambos frameworks foi bastante direta para a nossa utilização. Talvez com o Mocha sejam necessárias algumas configurações adicionais para adequar a legibilidade dos testes e incluir algumas funcionalidades para outros tipos de desafios. Neste ponto, o Jest facilitaria bastante o nosso trabalho.

Em termos de velocidade na execução dos testes, curiosamente o Mocha pareceu um pouco mais rápido. Talvez com um conjunto de testes maior esse resultado mude.

Instalar e configurar o Chai (uma biblioteca de asserções do Mocha) foi fácil e resolveu o meu maior incômodo com o framework.

De maneira geral, eu estaria bem confortável com o Jest, não fosse a tela de resultados dos testes tão poluída.

Considerando que é cada vez mais importante a capacidade de gerar valor rápido para as empresas, não me surpreende que o Jest esteja em crescimento. O fato do framework já vir por padrão com ferramentas integradas tem duas grandes vantagens, sendo a primeira delas a economia de trabalho inicial, já que não precisamos configurar outras ferramentas para o serviço. Essa característica também facilita a incorporação de pessoas aos times de desenvolvimento. Se com Mocha as ferramentas utilizadas podem variar consideravelmente, uma pessoa que domina o Jest pode, em teoria, ser capacitada para integrar quase qualquer projeto que utilize Jest sem grandes dificuldades. Isso pode ser especialmente importante em projetos grandes e de longa duração, como o Facebook.

Referências:

Foto de perfil do autor
André Kanamura

Dev na Campus Code