RSpec com Ruby puro

Tutoriais - 02/Jul/2019 - por André Kanamura

O RSpec é uma ferramenta de testes para Ruby muito poderosa. Pessoalmente, eu só havia utilizado o RSpec para desenvolvimento de aplicações Rails, mas quando comecei a trabalhar com o conteúdo de treinamentos da Campus Code, me deparei com uma situação nova: fazer testes RSpec com Ruby puro. Na Campus Code, os desafios são basicamente repositórios de projetos Ruby com testes para que os usuários implementem códigos que resolvam as falhas. Como eu nunca havia criado um projeto de Ruby puro do zero, não sabia como deveria ser a estrutura de arquivos para fazer o RSpec funcionar.

Primeiro criamos na pasta do projeto um arquivo Gemfile com as dependências do nosso código. Nesse caso, como não vamos fazer uma aplicação sofisticada, só precisamos de três gems:

source 'https://rubygems.org'

gem 'activesupport'
gem 'rake'
gem 'rspec'

Criamos também uma pasta '/bin' com um arquivo setup:

#!/usr/bin/env sh
set -e

bundle install

echo
echo '== Tudo configurado, pode iniciar ;) =='

Acima, configuramos o comando bin/setup para rodar o bundle install, que cria o ambiente adequado para desenvolver projetos Ruby instalando as gems necessárias. Você pode escolher a forma como preferir fazer essa configuração, mas, nesse exemplo, utilizamos a linguagem de comando sh para rodar o bundle install e imprimir no terminal a mensagem "Tudo configurado, pode iniciar ;)" caso tudo corra bem. A linha set -e, garante que, se algum problema ocorrer, o processo é abortado e a mensagem não aparece. Vale lembrar que é necessário rodar chmod +x bin/setup no Terminal para tornar o comando executável.

Além disso, o RSpec precisa de uma pasta '/spec' com um arquivo spec_helper.rb. Nele, basicamente, fica configurada a localização do código da nossa aplicação.

# frozen_string_literal: true

require 'active_support/all'
PROJECT_ROOT = File.expand_path('..', __dir__)

Dir.glob(File.join(PROJECT_ROOT, 'lib', '*.rb')).each do |file|
 autoload File.basename(file, '.rb').camelize, file
end

RSpec.configure do |config|
end

Opcionalmente, podemos fazer um arquivo rspec na pasta do projeto para definir a formatação das mensagens no Terminal:

--color
--format=documentation

Finalmente, criamos uma pasta '/lib' com o arquivo onde vamos escrever o código da nossa aplicação. Digamos que nosso exercício será fazer uma aplicação de uma calculadora, assim, vamos criar um arquivo com nome calculadora.rb. Com base nesse nome, criamos o arquivo de testes na pasta '/spec' chamado calculadora_spec.rb. Como o intuito deste artigo não é falar sobre a implementação da nossa calculadora, vamos focar no código dos testes:

require 'spec_helper'
require 'calculadora'

describe 'Calculadora' do
end

As duas primeiras linhas indicam os requerimentos do código. Em seguida definimos o bloco describe, que vai agrupar todos os testes que cobrem o funcionamento da Calculadora. Dentro desse bloco vamos começar o bloco it:

require 'spec_helper'
require 'calculadora'

describe 'Calculadora' do
  it 'deve somar elementos corretamente' do
    expect(soma(1, 3)).to eq(4)
  end
end

Nesse bloco descrevemos o que o teste deve avaliar e dentro dele implementamos o código. Normalmente estruturamos esse código em três partes: preparação, chamada do método e a verificação do resultado. Aqui conseguimos reduzir o teste para uma linha ao unir os elementos mais básicos. Chamamos o método na linha do expect, onde verifica-se o resultado esperado. Nesse caso, nosso teste verifica se o método soma realiza a soma dos parâmetros 1 e 3, resultando em 4.

Quando rodamos o comando rspec no Terminal obtemos o seguinte erro:

$ rspec

Calculadora
  deve somar elementos corretamente (FAILED - 1)

Failures:

  1) Calculadora deve somar elementos corretamente
     Failure/Error: expect(soma(1, 3)).to eq(4)

     NoMethodError:
       undefined method `soma' for #<RSpec::ExampleGroups::Calculadora:0x00005556ff6b9a30>
     # ./spec/calculadora_spec.rb:6:in `block (2 levels) in <top (required)>'

Finished in 0.00124 seconds (files took 0.2674 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/calculadora_spec.rb:5 # Calculadora deve somar elementos corretamente

A mensagem indica que o método soma não existe. Vamos definí-lo no arquivo calculadora.rb:

def soma(primeiro_numero, segundo_numero)
end

Se você rodar o rspec agora, o erro será diferente:

$ rspec
Calculadora
  deve somar elementos corretamente (FAILED - 1)

Failures:

  1) Calculadora deve somar elementos corretamente
     Failure/Error: expect(soma(1, 3)).to eq(4)

       expected: 4
            got: nil

       (compared using ==)
     # ./spec/calculadora_spec.rb:6:in `block (2 levels) in <top (required)>'

Finished in 0.11698 seconds (files took 0.27686 seconds to load)
1 example, 1 failure

Temos um erro bastante compreensível! Calculadora deve somar elementos corretamente, esperávamos 4, mas obtivemos nil. A partir daqui fica fácil para o usuário começar a implementar seu código. Em seguida, poderíamos escrever o código para as demais condições que queremos testar.

Este é apenas um exemplo de configuração e estrutura de código de testes. Independente da forma como você implementar a configuração, o usuário deve ser capaz de clonar seu repositório e rodar os testes do seu projeto de forma consistente.

Referências

Foto de perfil do autor
André Kanamura

Dev na Campus Code