2012-02-03 13 views
6

Teniendo en cuenta el código de abajo:rieles/RSpec - escritura de especificaciones para el método delegado (allow_nil opción)

(1) ¿Cómo haría usted para escribir una especificación para probar la: allow_nil => opción falsa?

(2) ¿Vale la pena escribir una especificación para probar?

class Event < ActiveRecord::Base 
    belongs_to :league 

    delegate :name, :to => :league, :prefix => true, :allow_nil => false 
end 

describe Event do 

    context 'when delegating methods to league object' do 
    it { should respond_to(:league_name) } 
    end 

end 

En realidad, sería bueno si pudiera extender la debería hacer:

it { should delegate(:name).to(:league).with_options(:prefix => true, :allow_nil => false) } 
+1

Es posible que desee considerar esto: alguien más hizo el trabajo por usted. https://gist.github.com/txus/807456 – weltschmerz

Respuesta

9

De acuerdo con la documentación del módulo delegate rieles:

Si el objeto delegado es nula una se plantea una excepción, y eso ocurre sin importar si nil responde al método delegado. Puede obtener un cero en su lugar con la opción: allow_nil.

me gustaría crear un objeto de evento event con una nula o establecidos event.league = nil, a continuación, tratar de llamar event.name, y comprobar que se produce una excepción, ya que eso es lo que se supone que sucede cuando allow_nil es falso (que también es el predeterminado). Sé rspec tiene este idioma para las pruebas de excepción:

lambda{dangerous_operation}.should raise_exception(optional_exception_class) 

no estoy seguro de si la debería haber tiene esta construcción, aunque hay are some articles, kinda old, about how to get this behavior in shoulda.

Creo que vale la pena probar si es el comportamiento que los usuarios de esta clase pueden esperar o suponer que sucederá, lo que creo que probablemente sea cierto en este caso. No me extendería para probar "debería delegar", porque eso parece más dependiente de la implementación: en realidad está diciendo que su Evento debería hacer una excepción si intenta llamar al #name cuando tiene una liga nula. Realmente no es importante para los usuarios del Evento cómo lo estás logrando. Incluso iría tan lejos, si desea afirmar y tomar nota de este comportamiento, para probar que Event#name tiene la misma semántica que League#name, sin mencionando algo sobre delegate, ya que este es un enfoque centrado en el comportamiento.

Cree sus pruebas según cómo se comporta su código, no cómo está construido; probar de esta manera es una mejor documentación para quienes tropiecen con sus pruebas, ya que están más interesados ​​en la pregunta "¿por qué se lanza mi Evento? " o "¿qué puede causar que Evento arroje?" que "¿este evento está delegando?".

Puede resaltar este tipo de situación imaginando qué fallas podrían ocurrir si cambia su código de una manera que a los usuarios de Event no les importe. Si no les importa, la prueba no se debe interrumpir cuando la cambien. ¿Qué sucede si quiere, por ejemplo, manejar la delegación usted mismo, escribiendo una función #name que primero registra o incrementa un contador y luego delegados al ? al probar el comportamiento de aumento de excepciones, está protegido de este cambio, pero al probar si Evento es un delegado, romperá esa prueba cuando realice este cambio, por lo que su prueba no fue lo que realmente es importante sobre la llamada al #name.

De todos modos, eso es todo solo charla soapbox. tl; dr: pruébelo si es un comportamiento en el que alguien pueda confiar.Todo lo que no se prueba es el gato de Shroedinger: roto y no roto al mismo tiempo. A decir verdad, la mayor parte del tiempo esto puede estar bien: es una cuestión de gusto si quieres decir algo riguroso y definitivo sobre cómo se debe comportar el sistema, o simplemente dejar que sea un "comportamiento no especificado".

+0

Tendrás que probar que la excepción es un RuntimeError; de lo contrario, el hecho de no delegar hará que no se encuentre un método. – fivetwentysix

2

Así que un par de cosas aquí de si o no para probar esto:

1) no creo que haya nada malo con spec'ing a cabo este comportamiento. Si tiene usuarios que necesitan aprender su software/biblioteca, a menudo es muy útil asegurarse de que todos sus métodos que son parte de su contrato público estén especificados. Si no quiere hacer esta parte de la API de este modelo, le recomiendo que haga la delegación manualmente para no exponer más métodos al mundo exterior de lo que necesita.

2) Las especificaciones de este tipo ayudan a asegurar que el contrato que usted tiene con el objeto que usted delega siga siendo ejecutado. Esto es particularmente útil si está utilizando trozos y burlas en sus pruebas, ya que a menudo están implementando el mismo contrato, por lo que al menos usted sabe cuándo cambia este contrato.

En términos de cómo se prueba la porción allow_nil, estoy de acuerdo con Matt, la mejor idea es asegurarse de que la liga es nula, luego intentar llamar a la liga. Esto podría probar para asegurar que se devuelva nil.

Espero que esto ayude.

Cuestiones relacionadas