Logo de La Coctelera

Tests de unidad en Rails, ¿qué testear?

4 Dic 06

El otro día lanzaba una pregunta al aire que nadie ha contestado, así que me contesto yo mismo y amplio la reflexión, a ver si alguien se anima a participar en el debate.

Mi pregunta era algo así como: cuando realizáis un test de unidad en Rails, ¿qué testeais? Pregunta justificada, tanto en cuanto el testing en general y en Rails en particular no es una ciencia exacta: nunca sabes cuánto testear, qué testear y si has hecho los suficientes tests.

Cuando Rabble estuvo en La Gran Corporación hablando sobre Testing en Rails alguien le preguntó cómo organizaba sus tests de unidad. Y si no recuerdo mal ni entendí mal (aunque por aquel entonces estaba yo aún un poco verde con el tema del testing) él contestó algo así como:

un test por cada validación realizada en el modelo

Pero claro, tú puedes testear para cada validación los valores que son válidos y aquellos que no lo son.

Sin embargo un test de unidad es algo más, pues se supone que al ser un test del modelo deberíamos también comprobar que las operaciones CRUD (creación, lectura, modificación y borrado también se llevan a cabo). Por tanto, cobra bastante sentido un test tal que así:

def test_crud
   m = MyClass.new
   m.att1 = value1
   m.att2 = value2
   ...
   m.attN = valueN
   assert m.save
   assert m.update_attribute(:attI, valueI)
   assert m.destroy
 end

Y por otro lado, cuando comienzas a escribir tests antes incluso de haber escrito el código de tu aplicación te das cuenta que tienes que escribir las fixtures a mano, lo cuál parece que sea lo normal, ya que existe una tarea de Rails que carga las fixtures en la base de datos de desarrollo.

Una vez has escrito dos, tres, cinco o veinte fixtures resulta bastante útil validarlas.

Esto se puede hacer también de forma bastante fácil con un simple test de unidad, que podéis incluir para clase testeada:

def test_fixtures
   MyClass.find(:all).each do |p|
     assert p.valid?
   end
 end

Además, aumentas tus estadísticas (rake stats) en tantos asserts como fixturas de la clase tengas.

En resumen, que para mi un test de unidad debe de tener, como mínimo:

  • un test por cada validación, tanto positivo como negativo
  • un test de las operaciones CRUD
  • un test de las fixtures

Dejo aquí un fichero con los tests de unidad de una clase Project perteneciente a un proyecto que tengo a medias con Ale (aunque él no lo sabe) en el que se ve todo lo que he ido explicando en el post y no se ha entendido.

¿Qué pensáis? ¿Demasiado exagerado o mejor cuanto más estricto y más encorsetado esté el modelo?

autor de la foto: Luis Villa

5 comentarios

5 comentarios

  1. 4 Dic 2006 | 11:33 AM # Juan Lupión dice:

    Supongamos que tengo un atributo validado por 'validates_uniqueness'. Si preparo un test en el que creo un objeto y le asigno a ese atributo un valor que ya existe en uno de ms fixtures, y compruebo que el objeot así generado no es válido, ¿estoy probando mi modelo o estoy realmente probando 'validates_uniqueness' ? De eso ya se encargan las pruebas del core de Rails. ¿No estaría repitiéndome? Lo mismo para las asociaciones sencillas.

    Yo me limito a comprobar las validaciones y funciones del modelo escritas por mí; con la unica salvedad de 'validates_format_of' que también pruebo para comprobar que la expresión de formato es la correcta.

    A veces he tenido que modelar relaciones complejas y sí escribo tests para las mismas, pero más que para cmprobar que funcionan lohago casi como documentación, para luego poder echar un vistazo a los fixtures y deducir qué se supone que hacen las relaciones :) Lo que no se me había ocurrido es pasar que todas las fixtures son válidas, que sí que es interesante.

  2. 4 Dic 2006 | 12:37 PM # sergio dice:

    Pues mira que Rabble y tú me caéis bien y creo que sabéis mucho, pero aquí estoy con Juan (que también me caéis bien y sabe): no creo que tenga sentido probar Rails, que ya viene con su batería de pruebas. Hacer un test que pruebe si en mi modelo está funcionando bien has_many y belongs_to parece un poco absurdo, pues ya sabemos que funcionan bien. Con, quizá, la única excepción del TDD, donde yo escribo el test que describe la funcionalidad que quiero, y luego hago pasar el test colocando el has_many y el belongs_to. Y con las validaciones obvias, pues lo mismo. Excepción hecha como tú has dicho del validates_format_of, donde realmente sí escribimos código de nuestra cosecha, aunque sea una expresión regular (ja!). Obviamente sí hay que testear nuestro código del modelo, tanto nuestras validaciones, como nuestros callbacks, como cualquier método que añadamos.

    Otra excepción cuando a lo mejor sí que podemos testear código de Rails (sigo con el ejemplo de las relaciones), es cuando estas relaciones son suficientemente complejas como para poder no estar seguro de haber puesto las llamadas adecuadas en el modelo adecuado y con los parámetros adecuados. Si, por ejemplo, mezclas polimorfismo con herencia simple y con algún :through, ahí puede ser bueno testear porque es muy fácil haber metido la gamba. Pero no estás probando métodos de Rails, sino tú capacidad de usarlos de forma adecuada.

  3. 4 Dic 2006 | 10:27 PM # Fernando dice:

    Wow! Pedazo de comentarios y cargados de razón.

    Sin embargo, en mi defensa quiero alegar que para mí comprobar que mi modelo no duplica un atributo que le he indicado que no duplique no es testear Rails, sino comprobar que cumple con su especificación.

    Rabble creo que habló durante la charla, o si no antes, de utilizar los tests de Rails como una especificación funciona y cerrada que debería de cumplir nuestra aplicación. Algo así como el contrato. Si nuestra aplicación pasa los tests significa que por nuestro lado hemos cumplido.

    Por supuesto que no pretendo testear Rails, que seguro que funciona muy bien, sino más bien asegurarme de que lo que estoy intentado implementar sea que lo tengo pensado.

  4. 5 Dic 2006 | 12:36 AM # demimismo dice:

    Yo soy aún über-newbie en Rails, pero en esto estoy con Blat: no se trata de testear Rails, sino el modelo. Supongo que esto toma especial importancia con la desnormalización, aunque no se si Rails proporciona mecanismos automáticos para esto, ya digo que soy novatillo :-)

    También creo que los test de unidad no deben aplicarse únicamente al modelo, Supongo que igualmente se deben probar unidades de software que sean mínimamente complejas (aserciones relacionadas con las requests en controladores, por poner un ejemplo).

  5. 10 Ene 2007 | 09:06 AM # in web we trust dice:

    Ya lo dije hace días cuando hablé de tests de unidad en Rails y hoy me reafirmo: ¡testea tus fixtures...

Escriba un comentario: