Mudança no RSpec 1.1.4 remove inclusão automática de módulos

25/06/08

No RSpec 1.1.4, a inclusão de módulos deixou de ser automática. Você só irá perceber esta mudança se está testando algum módulo, como é o caso dos helpers.

Antes, você só precisava fazer algo como isto:

describe ApplicationHelper do
  it "should render flash[:notice]" do
    flash[:notice] = "Some notice"
    flash_messages.should have_tag('p.notice', 'Some notice')
  end
end

Nesta nova versão, se você tentar testar o método flash_messages, irá receber uma mensagem de aviso: Modules will no longer be automatically included in RSpec version 1.1.4. Called from ./spec/helpers/application_helper_spec.rb:6

A solução é fazer a inclusão manual dos módulos, como este exemplo

describe ApplicationHelper do
  include ApplicationHelper
 
  it "should render flash[:notice]" do
    flash[:notice] = "Some notice"
    flash_messages.should have_tag('p.notice', 'Some notice')
  end
end

ou utilizar o objeto helper, que possui todos os métodos do módulo especificado em describe

describe ApplicationHelper do
  it "should render flash[:notice]" do
    flash[:notice] = "Some notice"
    helper.flash_messages.should have_tag('p.notice', 'Some notice')
  end
end

Em um primeiro momento, eu não tinha gostado nem um pouco desta alteração, mas depois de ler os motivos, acho que ficou muito melhor. Você teria dúvidas de que está testando um helper se utilizar helper.flash_messages? E se você tivesse um módulo com um método describe? As respostas já justificam a alteração por si sós.

Otimizando o Autotest

20/06/08

Toda vez que executo o Autotest, não demora muito para o cooler do meu Macbook[bb] ligar e parecer que vai decolar! O problema é que o Autotest busca alterações nos arquivos a cada segundo, o que ocasiona um uso muito intenso da CPU.

Para resolver este problema, basta você aumentar este tempo de verificação que, no exemplo abaixo, foi definido como 5 segundos. Além disso, podemos ignorar alguns diretórios, diminuindo os arquivos que precisam ser verificados. Abra seu arquivo "~/.autotest" e adicione o código abaixo.

Autotest.add_hook :initialize do |at|
 at.sleep = 5
 %w{.svn .git public vendor}.each { |exception| at.add_exception(exception) }
end

Simples, rápido e, o melhor de tudo, silencioso!

Testando métodos privados e protegidos no Ruby

17/06/08

Se você precisa testar métodos privados e/ou protegidos, faça isso de uma maneira elegante, sem se enrolar à toa.

Imagine que você tenha uma classe como esta:

class Emo
  private
    def deny
      "i'm not a emo! i'm from uk!"
    end
 
  protected
    def cut_wrists
      "oh god! nobody loves me! i'm gonna cut my wrists!"
    end
end
 

Para testar estes métodos, você pode usar o método send.

require "test/unit"
 
class TestEmo < Test::Unit::TestCase
  def setup
    @emo = Emo.new
  end
 
  def test_should_cut_wrists
    assert_equal @emo.send(:cut_wrists), "oh god! nobody loves me! i'm gonna cut my wrists!"
  end
 
  def test_should_deny_condition
    assert_equal @emo.send(:deny), "i'm not a emo! i'm from uk!"
  end
end

Uma dica rápida, mas que nem todos conhecem. Simples e muito, muito elegante!

Update: Ah, isso deixará de funcionar no 1.9 (você terá que usar o método send!), mas você pode corrigir isso quando ele for lançado, pois os testes que você escreve pegarão tal erro, certo? :)

Update 2: Quando o comportamento do send realmente mudar, acho que algo como isso irá resolver a situação (embora não tenha testado).

class Object
  def send(*args)
    send!(*args)
  end
end