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

Comentários #


#1 David disse:
17 Jun 08, 03:19PM

Muito bom o post :)

#2 Marco Gomes disse:
17 Jun 08, 03:56PM

Adorei o "tema" do exemplo :)

#3 Davis Zanetti Cabral disse:
17 Jun 08, 04:08PM

Matou um problema bicho! Mto bom mesmo!

#4 ArthurGeek disse:
17 Jun 08, 04:14PM

Muuito elegante mesmo! Mas, faltou dizer se você é Emo ou não! :P

#5 Phillip Calçado disse:
18 Jun 08, 06:17AM

Object#send salva vidas muitas vezes mas testes unitários em OO deveriam focar na classe e não no método. Testar métodos privados pode inciar que voc6e está quebrando a abstração principal…

http://fragmental.tw/2008/01/08/please-do-not-break-into/

[]s

#6 Nando Vieira disse:
18 Jun 08, 07:50AM

Phillip, embora concorde com o seu argumento, existem momentos que *preciso* testar métodos privados/protegidos.

Tomemos como exemplo um sistema de autenticação no Rails. Meus métodos de verificação estão como private no "Application.rb" pois eles devem estar disponíveis apenas para controllers e views, e não podem ser identificados como rotas.

Neste caso, faz todo o sentido eu escrever testes unitários para os métodos que compõe a classe Application (logged? ou current_user, por exemplo), pois não necessariamente eles possuem uma abstração principal.

Faz sentido? Como você faria seus testes neste caso?

#7 Tapajós disse:
18 Jun 08, 04:43PM

Quando caio nesse seu problema uma solução que eu sempre uso é: http://pastie.org/217489

Deixe um comentário




Este blog usa o Gravatar.


Não é aceito código HTML:
adicione-o no pastie.caboo.se ou paste.milk-it.net e poste apenas o link.

Se este é seu primeiro comentário, ele terá que ser aprovado antes de ser exibido.