Anotações do Hercules

Criando seus próprios matchers para RSpec

09-07-2015

Escrevendo código para nossos programas costumamos usar várias técnicas para evitar repetições. Nos testes automatizados não é diferente, é código e precisa ser mantido também, precisa ser algo fácil de entender.

Digamos que temos um método que devolve uma resposta http que vamos retornar como uma resposta do rack.

def responds_ok(message)
  [200, { 'Content-Type' => 'text/html' }, [message]]
end

RSpec.describe '#responds_ok' do
  it 'returns status ok' do
    response = responds_ok('my message')
    expect(response[0]).to eq 200
  end

  it 'returns my message' do
    msg = 'my message'
    response = responds_ok(msg)
    expect(response[2]).to eq [msg]
  end
end

Essas specs são bem simples, mas força a pessoa que vai lê-las a entender que o retorno é um array, que o primeiro valor é o status e o terceiro valor é a mensagem, e nesse último caso, que a mensagem seja um outro array. Para quem escreveu esse código inicialmente pode parecer algo óbvio, mas temos uma maneira melhor de fazer essas verificações. Uma boa alternativa nesse caso é criar nossos próprios matchers.

require 'rspec/expectations'

RSpec::Matchers.define :be_ok do
  match do |response|
    response[0] == 200
  end
end

RSpec::Matchers.define :have_message do |message|
  match do |response|
    response[2].join == message
  end
end

Matchers podem simplesmente verificar um valor, ou comparar diferentes valores passados como parâmetro. No código acima podemos ver que é bem simples definir um novo matcher com RSpec, basta passar um bloco para o método match que retorne um valor booleano.

Desta maneira, as specs podem ser escritas da seguinte maneira:

RSpec.describe '#responds_ok' do
  it 'returns status ok' do
    response = responds_ok('my message')
    expect(response).to be_ok
  end

  it 'returns my message' do
    msg = 'my message'
    response = responds_ok(msg)
    expect(response).to have_message(msg)
  end
end

Bem mais agradável aos olhos, não é mesmo?!

RSpec custom matchers

comments powered by Disqus