Object Mother, mas allá de los Builders

Hace unas semanas os hablé sobre los builders y como estos nos servían para simplificar significativamente nuestros tests. Hoy iremos un paso más allá usando el concepto Object Mother.

Que es una Object Mother?

La primera vez que leí acerca de las Object Mother fue en este articulo de Martin Fowler.

En él explica que estas Object Mother son clases que nos permiten crear ejemplos de nuestras clases con un comportamiento predefinido. Ni más ni menos, como podéis ver el concepto es muy sencillo y su implementación también.

Ejemplo de uso

Después de esta introducción y siguiendo donde lo habíamos dejado en el post de los builders con un código tal que así:

student = StudentBuilder().with_country("Spain").build()

La idea es expresar de una forma aún más clara y semántica que es lo que necesitamos en nuestros test y hacerlo mediante un método de una clase auxiliar (personalmente me gusta llamarla TestData)

spanish_student = TestData.a_spanish_student()

¿Y como podemos lograr expresar en código la creación de un alumno nacido en España? Pues como ya os podéis imaginar es haciendo uso de los builders:

from student_builder import StudentBuilder

class TestData:
  @staticmethod
  def a_spanish_student() -> Student:
    return StudentBuilder().with_country("Spain").build()

¿Se entiende la idea verdad? Yo creo que es bastante sencillo así que veamos algún ejemplo más:

adult_spanish_student = TestData.an_adult_spanish_student()
adult_spanish_student_called_peter = TestData.an_adult_spanish_student_called_peter()

La implementación de los métodos sería tal que así:

from student_builder import StudentBuilder

class TestData:
  @staticmethod
  def a_spanish_student() -> Student:
    return StudentBuilder().with_country("Spain").build()

  @staticmethod
  def an_adult_spanish_student() -> Student:
    return StudentBuilder().with_age(20).with_country("Spain").build()

  @staticmethod
  def an_adult_spanish_student_called_peter() -> Student:
    return (
      StudentBuilder()
        .with_age(20)
        .with_country("Spain")
        .with_name("Peter")
        .build()
      )

Como veis haciendo uso de los builders las posibilidades son casi infinitas.

Conclusiones

Como hemos podido ver el uso de Object Mother junto con los builders es una forma súper útil de dar aun más semántica a nuestros tests.

Pero es importante decir también que este tipo de clases en nuestros tests usadas en exceso puede llegar a ser más perjudiciales que beneficiosas. Esto se debe a que si no somos capaces de expresar claramente que hacen nuestras Object Mothers la gente que no tenga conocimiento del código tendrá que ir a mirar que hacen nuestras Object Mothers.

De igual forma si muchos tests depende de estas clases posteriores cambios en las mismas pueden ser un dolor de cabeza que nos hará tener que actualizar todos esos tests.

¡Un saludo!