Pruebas Unitarias: Proveedores de datos
A menudo, cuando realizamos pruebas unitarias de algún problema algorítmico, nos encontramos con muchos tests iguales. Tan solo cambia la entrada y el resultado.
La mayor parte de los XUnit ya se han dado cuenta de esto y por eso han implementado soluciones. El problema es que no se han puesto de acuerdo en la nomenclatura ni en la implementación.
Veremos aquí aproximaciones en Java, PHP y Python.
Java: Parametrized
Poca gente sabe (y yo lo he descubierto hace poco) que JUnit 4 incluyó los tests parametrizados.
En Java todo son clases. No se puede pasar un puntero a función, lo que complica terriblemente cosas realmente sencillas. y éste es uno de esos casos.
Vamos a hacer un ejemplo básico: Fibonacci. Como sabréis, los dos primeros números valen 1 y el resto se genera sumando los dos anteriores. ¡A por ello!
|
|
Mucho código y poca chicha. Vamos por las cosas importantes:
Cambiando el ejecutor
Pues eso, que tenemos que decirle a JUnit que el ejecutor es Parameterized
en lugar del que utiliza por defecto:
|
|
Constructor
El constructor debe recibir como argumentos lo que queramos usar en los tests. Es una restricción por utilizar el @Test
, que requiere una función sin argumentos.
Generador
Ahora necesitamos una función que genere los argumentos. Ésta será una función estática que devuelve un Collection
y marcada con la anotación adecuada:
|
|
En este caso he decidido devolver los números a mano, claro.
Tests
Finalmente, los tests, en los que se utilizan los argumentos.
Ejecución
Y ejecutamos los tests normalmente, pero veremos que ha realizado más tests de los habituales (para ejecutarlos usé maven, pero sabéis que no es necesario):
|
|
El código
Os pego el código de la función principal por si queréis probarlo:
|
|
PHP
En PHP todo es más fácil, menos hacer las cosas bien. Aquí lo pondré todo junto:
|
|
Como he dicho, todo es más fácil, se entiende más fácil, pero no está bien hecho. Odio tener código en comentarios, y aquí se indica que se utilice el “dataProvider” en un comentario. Los comentarios son para comentar. Y punto.
Pero dejemos ya de juzgar a PHP, cosa que resulta tremendamente sencilla. Vamos a ver lo que he hecho.
Proporcionando datos
Pues nada: una función que devuelve un array de arrays.
Escribiendo el test
Se pone un comentario (eso sí: ¡¡con doble asterisco!!) y se indica qué función es la que va a proporcionar los datos. Y ya.
Cada dato provocará una llamada a la función de tests.
Comparativa entre JUnit y PHPUnit
Como véis, en PHP ha resultado mucho más sencillo. Además, en Java tiene un problema: todos los tests se ejecutarán con todos los datos. No hay manera de especificar distintos proveedores de datos para dos funciones, sino separándolos a dos clases.
En PHP es horrible eso de usar anotaciones embebidas en comentarios. Bueno… Todo en PHP es horrible.
Python
Pues…. Ya he terminado. Python no soporta este tipo de características.
Tienen abierta una incidencia, pero no parecen por la labor de implementarlo. Dicen que es tan sencillo simularlo que no interesa. Yo, personalmente, no estoy de acuerdo. A mí me gusta eso de ver un punto por cada test y que me indique exactamente cuál es el que ha fallado.
Por otra parte, creo que nose proporciona una manera, pero no en la versión disponible en Debian. Quizá cuando sea oficial cambiaré esta entrada :D
De todas maneras, siempre podéis utilizar BDD , mediante freshen , que sí soporta estas características, como ya expliqué en el artículo Python: Cómo hacer pruebas 5: freshen.
Más información
Para Java, os recomiendo la web de Isagoksu, `Using JUnit Parameterized Annotation].
Para PHP, el propio manual de PHPUnit, en la sección de Data Providers.
Y para Python, ya os dije que no hay nada, y que lo mejor que podéis hacer es usar BDD mediante freshen y mi artículo en castellano Python: Cómo hacer pruebas 5: freshen.