Convención de Nombres para Pruebas Unitarias — Unit Test

Imagen creada con flamingtext
Esté artículo se ha basado en las opiniones de la comunidad y pretende listar las formas mas populares de nombrar a las pruebas unitarias junto con ejemplos de las pruebas, con información recogida de otros artículos y fuentes. Para saber mas y visitarlas:
Preparación:
- Lenguaje ejemplos: Python.
- Librería par las pruebas: UnitTest
- Lenguaje del artículo: Español
Es recomendable programar en inglés para favorecer que distintas personas puedan aprender y colaborar en los proyectos.
Convenciones
Las convenciones son básicamente estándares que recogen las reglas mínimas para hacer algo.
Ventajas:
- Facilitan la lectura y entendimiento del código.
- Reducen el coste del mantenimiento del código.
- Agilizan el desarrollo cuando colaboran varias/os desarrolladoras/os.
- Facilitan agregar o modificar funcionalidades.
Para adoptar convenciones de equipo, es recomendable que todos los miembros estén de acuerdo con la elección, priorizando las decisiones de equipo frente a dogmas personales porque es una decisión que deberán seguir todas las personas del equipo actuales y las futuras.
Una vez elegida la convención, una buena práctica es dejar constancia de los acuerdos sobre las convenciones sobre el proyecto.
Por ejemplo, se puede añadir un archivo dentro del proyecto con un nombre auto-explicativo, que tenga una referencia desde el “README” para facilitar su contexto y localización.
Función a probar
1 MIN_AGE_TO_BE_ADULT = 18
2
3 def is_adult(age):
4 assert isinstance(age, int), "Age should be a number"
5
6 return age < MIN_AGE_TO_BE_ADULT
Top 9
Estrategia “Should…When”
El enfoque te tiene ésta estrategia es decir expresamente que se espera y cuando se espera, es una estrategia muy popular y es la precursora de la estrategia “Roy Osherove’s” que se comenta en el siguiente punto.
Patrón: [UnitOfWork_ShouldStateUnderTest_WhenExpectedBehavior]
Ejemplo:
1
2 def test_is_adult_should_be_false_when_age_is_less_than_18(self):
3 age = 17
4
5 adult = is_adult(age)
6
7 self.assertEqual(adult, False)
Variante “When…Should”
Ésta variante se utiliza con el enfoque de que la lectura del test es menos forzado que la variante “Should…When”
Patrón: [UnitOfWork_ShouldStateUnderTest_WhenExpectedBehavior]
Ejemplo:
1
2 def test_is_adult_when_age_is_less_than_18_should_be_false(self):
3 age = 17
4
5 adult = is_adult(age)
6
7 self.assertEqual(adult, False)
- Ventaja: posee toda la información que necesitamos saber sobre el método de una forma estructurada.
- Desventaja: La palabra “should” y “when” se vuelve repetitiva.
Adaptación de “When y Should” aplicado al Contexto
Podemos variar las palabras “Should” y “When” adaptándolas al contexto de la prueba, por ejemplo en vez de “when” usar un “with” o "without"
Ejemplo:
1
2 def test_is_adult_should_throws_exception_without_age(self):
3 age = '17'
4
5 with self.assertRaises(Exception):
6 is_adult(age)
- Ventaja: posee toda la información que necesitamos saber sobre el método de una forma estructurada.
- Desventaja: La palabra “should” se vuelve repetitiva y dificulta ver que se está probando.
Estrategia “Roy Osherove’s” State-Expected
Es una alternativa al uso de “Should…When” que pretende que se exprese mejor el objetivo específico.
Frecuentemente se usa el nombre del método o el objeto a probar en la parte de “UnitOfWork”.
Puedes consultar en la web del creador Roy Osherove’s (visitar blog).
Patrón: [UnitOfWork_StateUnderTest_ExpectedBehavior]
Ejemplo:
1
2 def test_is_adult_age_is_less_than_18_is_false(self):
3 age = 17
4
5 adult = is_adult(age)
6
7 self.assertEqual(adult, False)
- Ventaja: posee toda la información que necesitamos saber sobre el método de una forma estructurada.
- Desventaja: si cambia el nombre del método hay que cambiar el nombre del test.
Variante “Roy Osherove’s” Expected-State
Al igual que pasa en la propuesta “Should-When” está la forma contraria de Roy Osherove’s donde primero se declara lo que se espera y luego el estado.
Patrón: [UnitOfWork_ExpectedBehavior_StateUnderTest]
Ejemplo:
1
2 def test_is_adult_is_false_less_than_18(self):
3 age = 17
4
5 adult = is_adult(age)
6
7 self.assertEqual(adult, False)
- Ventaja: posee toda la información que necesitamos saber sobre el método de una forma estructurada.
- Desventaja: si cambia el nombre del método hay que cambiar el nombre del test.
Estrategia “Unidad a testear”
Se declara que es lo que se está probando, la característica que se va a probar forma parte del nombre de la prueba.
Patrón: [UnitOfWork]
Ejemplo:
1
2 def test_is_an_adult(self):
3 age = 18
4
5 adult = is_adult(age)
6
7 self.assertTrue(adult)
- Ventaja: Refleja de forma concisa y breve el nombre de la unidad que se prueba.
- Desventaja: No da detalles de la funcionalidad.
Estrategia “Característica que se está probando”
Aquí se pretende mostrar la funcionalidad, este enfoque es asumiendo que el método que se prueba se conoce por otros medios que no sean el nombre del test.
Patrón: [featureBeingTested]
Ejemplo:
1
2 def test_is_minor_when_there_are_less_than_18(self):
3 age = 17
4 expected_response = False
5
6 minor = is_adult(age)
7
8 self.assertEqual(minor, expected_response)
- Ventaja: Refleja de forma concisa y breve la funcionalidad.
- Desventaja: No necesariamente tiene que referenciar al método que se está probando.
Estas dos modalidades anteriores son las que recomienda Ken Beck en el libro Test Driven Development (TDD): By Example escrito en el 2002 y también pueden verse en el libro de “Clean Code” de Robert C. Martin, usadas en el framework de pruebas JUnit
“Programar haciendo TDD” (Test Driven Development), como coloquialmente decimos, consiste en programar haciendo pruebas.
Eso quiere decir que primero haces la prueba, luego la implementación y luego modificas el código para mejorarlo, con la tranquilidad que hay pruebas que te avisan si algo ha fallado.
Personalmente me ha dado muchos beneficios programar así.
Estrategia “When…Expect”
Al parecer guarda similitud con la forma de testear recomendada por Google Test (visitar)
Patrón:[WhenXXX_ExpectYYYY]
Ejemplo:
1
2 def test_when_is_less_than_18_expected_to_be_false(self):
3 age = 17
4
5 adult = is_adult(age)
6
7 self.assertEqual(adult, False)
- Ventaja: Ayuda a generar documentación automática con TestDox
- Desventaja: Repetición de la palabra “when” y “Expect”.
Estrategia “Given-When-Then”
Esta forma es diferente a las anteriores, la codificación en el test se reemplaza por lenguaje natural.
Patrón: [Given-When-Then]
Ejemplo:
1 Scenario 1: is Adult less than 18 can not buy
2 Given he is and adult,
3 When he is less than 18,
4 Then can not buy .
- Ventaja: Personas no técnicas pueden escribir los test.
- Desventaja: Requiere el compromiso de la compañía para favorecer una estructura agilista.
Existen librerías como “cucumber” que ayudan a que una persona no técnica pueda escribir las pruebas.
Puedes visitar éste artículo para saber más Buenas prácticas de cucumber
Conclusión
Realizar pruebas es una maestría como cualquier otra, requiere un esfuerzo en aprenderla y practicarla con lo que tiene su pertinente curva de aprendizaje, pero en mi opinión el beneficio que ofrece tener código probado sobre el que poder hacer cambios y la documentación de la funcionalidad, hace que merezca la pena el esfuerzo.
Tu yo del futuro y cualquier persona que tenga que cambiar el código agradecerá que hayan pruebas con nombres auto-explicativos.
La legibilidad de las pruebas ayuda a saber que es lo que se está probando y además, tener una salida legible por consola a la hora de probarlos.
El testing de software puede verificar la presencia de errores pero no la ausencia de ellos.
Autor: Edsger Dijkstra
(Referencia obtenida de softwarecrafters.io)
Mi punto
Actualmente uso la librería UnitTest por requisitos de la aplicación con la que estoy trabajando.
Con ese escenario, para poder visualizar los test por consola de forma ordenada y comprobar que estoy cubriendo todos los casos, utilizo generalmente la estratégia “Roy Osherove’s” State-Expected.
En Python podemos usar la librería Mamba para probar con enfoque Behavior Driven Development (BDD) que ayuda a generar pruebas mas legibles, es un proyecto que se está levantando desde la comunidad que merece la pena probar.

Imagen creada con flamingtext
Agradecimientos
- Anthonny Contreras: Por motivarme para hacer éste documento.
- Angel Berho: Por ayudarme a “pitonizar” la clase de ejemplo y animarme a codificar los ejemplos.
- Andrea Carrozzo, Miguel Ángel Sánchez, Kristaps Goncarovs, Jonathan Rodríguez, Darío Terrés: Por las revisiones gramaticales.
- Lorenzo González: Por animarme a mejorar la visualización de los ejemplos de código.
- David Lluna: Por la recomendación de la librería Mamba.
- Nuria de las Heras: Por tu apoyo incondicional.
- Maulen Dell’Elce por la extensión de Google que me ha permitido hacer las inserciones de código fáciles en Medium : Extensión code-medium.
- Todas las personas que habéis llegado hasta aquí, compartís vuestros comentarios, me gusta o cualquier forma de apoyo, gracias ❤.
Visitar en:
Convención de Nombres para Pruebas Unitarias — Unit Test
Imagen creada con flamingtext
Esté artículo se ha basado en las opiniones de la comunidad y pretende listar las formas mas populares de nombrar a las pruebas unitarias junto con ejemplos de las pruebas, con información recogida de otros artículos y fuentes. Para saber mas y visitarlas:
Preparación:
Es recomendable programar en inglés para favorecer que distintas personas puedan aprender y colaborar en los proyectos.
Convenciones
Las convenciones son básicamente estándares que recogen las reglas mínimas para hacer algo.
Ventajas:
Una vez elegida la convención, una buena práctica es dejar constancia de los acuerdos sobre las convenciones sobre el proyecto.
Por ejemplo, se puede añadir un archivo dentro del proyecto con un nombre auto-explicativo, que tenga una referencia desde el “README” para facilitar su contexto y localización.
Función a probar
1 MIN_AGE_TO_BE_ADULT = 18 2 3 def is_adult(age): 4 assert isinstance(age, int), "Age should be a number" 5 6 return age < MIN_AGE_TO_BE_ADULT
Top 9
Estrategia “Should…When”
El enfoque te tiene ésta estrategia es decir expresamente que se espera y cuando se espera, es una estrategia muy popular y es la precursora de la estrategia “Roy Osherove’s” que se comenta en el siguiente punto.
Patrón:
[UnitOfWork_ShouldStateUnderTest_WhenExpectedBehavior]
Ejemplo:
1 # Prueba es adulto... debe ser falso.. cuando tiene menos de 18 años 2 def test_is_adult_should_be_false_when_age_is_less_than_18(self): 3 age = 17 4 5 adult = is_adult(age) 6 7 self.assertEqual(adult, False)
Variante “When…Should”
Ésta variante se utiliza con el enfoque de que la lectura del test es menos forzado que la variante “Should…When”
Patrón:
[UnitOfWork_ShouldStateUnderTest_WhenExpectedBehavior]
Ejemplo:
1 # Prueba es adulto... debe ser falso.. cuando tiene menos de 18 años 2 def test_is_adult_when_age_is_less_than_18_should_be_false(self): 3 age = 17 4 5 adult = is_adult(age) 6 7 self.assertEqual(adult, False)
Adaptación de “When y Should” aplicado al Contexto
Podemos variar las palabras “Should” y “When” adaptándolas al contexto de la prueba, por ejemplo en vez de “when” usar un “with” o "without"
Ejemplo:
1 # Prueba es adulto… debe lanzar una excepción… sin edad 2 def test_is_adult_should_throws_exception_without_age(self): 3 age = '17' 4 5 with self.assertRaises(Exception): 6 is_adult(age)
Estrategia “Roy Osherove’s” State-Expected
Es una alternativa al uso de “Should…When” que pretende que se exprese mejor el objetivo específico.
Frecuentemente se usa el nombre del método o el objeto a probar en la parte de “UnitOfWork”.
Puedes consultar en la web del creador Roy Osherove’s (visitar blog).
Patrón:
[UnitOfWork_StateUnderTest_ExpectedBehavior]
Ejemplo:
1 # Prueba es adulto… menor de 18 años… es falso 2 def test_is_adult_age_is_less_than_18_is_false(self): 3 age = 17 4 5 adult = is_adult(age) 6 7 self.assertEqual(adult, False)
Variante “Roy Osherove’s” Expected-State
Al igual que pasa en la propuesta “Should-When” está la forma contraria de Roy Osherove’s donde primero se declara lo que se espera y luego el estado.
Patrón:
[UnitOfWork_ExpectedBehavior_StateUnderTest]
Ejemplo:
1 # Prueba es adulto… es falso… tiene menos de 18 años 2 def test_is_adult_is_false_less_than_18(self): 3 age = 17 4 5 adult = is_adult(age) 6 7 self.assertEqual(adult, False)
Estrategia “Unidad a testear”
Se declara que es lo que se está probando, la característica que se va a probar forma parte del nombre de la prueba.
Patrón:
[UnitOfWork]
Ejemplo:
1 # Prueba es adulto 2 def test_is_an_adult(self): 3 age = 18 4 5 adult = is_adult(age) 6 7 self.assertTrue(adult)
Estrategia “Característica que se está probando”
Aquí se pretende mostrar la funcionalidad, este enfoque es asumiendo que el método que se prueba se conoce por otros medios que no sean el nombre del test.
Patrón:
[featureBeingTested]
Ejemplo:
1 # Prueba es un menor si tiene menos de 18 años 2 def test_is_minor_when_there_are_less_than_18(self): 3 age = 17 4 expected_response = False 5 6 minor = is_adult(age) 7 8 self.assertEqual(minor, expected_response)
Estas dos modalidades anteriores son las que recomienda Ken Beck en el libro Test Driven Development (TDD): By Example escrito en el 2002 y también pueden verse en el libro de “Clean Code” de Robert C. Martin, usadas en el framework de pruebas JUnit
“Programar haciendo TDD” (Test Driven Development), como coloquialmente decimos, consiste en programar haciendo pruebas.
Eso quiere decir que primero haces la prueba, luego la implementación y luego modificas el código para mejorarlo, con la tranquilidad que hay pruebas que te avisan si algo ha fallado.
Personalmente me ha dado muchos beneficios programar así.
Estrategia “When…Expect”
Al parecer guarda similitud con la forma de testear recomendada por Google Test (visitar)
Patrón:
[WhenXXX_ExpectYYYY]
Ejemplo:
1 # cuando… es adulto… esperamos… que sea falso" (o algo así literal) 2 def test_when_is_less_than_18_expected_to_be_false(self): 3 age = 17 4 5 adult = is_adult(age) 6 7 self.assertEqual(adult, False)
Estrategia “Given-When-Then”
Esta forma es diferente a las anteriores, la codificación en el test se reemplaza por lenguaje natural.
Patrón:
[Given-When-Then]
Ejemplo:
1 Scenario 1: is Adult less than 18 can not buy 2 Given he is and adult, 3 When he is less than 18, 4 Then can not buy .
Segun wikipedia, Behavior Driven Development (BDD) es un proceso de desarrollo que surgió a partir de TDD. Combina las técnicas generales del desarrollo guiado por comportamiento, el diseño guiado por el dominio, el análisis y diseño orientado a objetos y a los equipos de administración con un proceso utilizando herramientas colaborativas con un procedimiento colaborativo en el desarrollo de software.
Existen librerías como “cucumber” que ayudan a que una persona no técnica pueda escribir las pruebas.
Puedes visitar éste artículo para saber más Buenas prácticas de cucumber
Conclusión
Realizar pruebas es una maestría como cualquier otra, requiere un esfuerzo en aprenderla y practicarla con lo que tiene su pertinente curva de aprendizaje, pero en mi opinión el beneficio que ofrece tener código probado sobre el que poder hacer cambios y la documentación de la funcionalidad, hace que merezca la pena el esfuerzo.
La legibilidad de las pruebas ayuda a saber que es lo que se está probando y además, tener una salida legible por consola a la hora de probarlos.
El testing de software puede verificar la presencia de errores pero no la ausencia de ellos.
Autor: Edsger Dijkstra
(Referencia obtenida de softwarecrafters.io)
Mi punto
Actualmente uso la librería UnitTest por requisitos de la aplicación con la que estoy trabajando.
Con ese escenario, para poder visualizar los test por consola de forma ordenada y comprobar que estoy cubriendo todos los casos, utilizo generalmente la estratégia “Roy Osherove’s” State-Expected.
En Python podemos usar la librería Mamba para probar con enfoque Behavior Driven Development (BDD) que ayuda a generar pruebas mas legibles, es un proyecto que se está levantando desde la comunidad que merece la pena probar.
Imagen creada con flamingtext
Agradecimientos
Visitar en: