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.