Publicado por en
A la hora de escribir pruebas unitarias los Stubs y Mocks son herramientas clave. Se utilizan para imitar el comportamiento de objetos que devuelven resultados no determinísticos, depende de un estado difícil de crear o son lentos. Por ejemplo, una base de datos o un API. Los valores que se obtienen de estos dependerán de su estado y, por lo tanto, no se pude garantizar que sea siempre el deseado cuando se ejecuta la prueba. Otro ejemplo de uso puede ser un método que requiera un tiempo considerable para devolver el resultado. Para solucionar estos problemas es necesario saber escribir Stub y Mocks en las pruebas. El paquete testthat
contienen herramientas que permiten escribir Mocks en R.
¿Qué es un Mocks?
En las pruebas unitarias los Mocks son objetos programados que simulan el comportamiento de otros objetos reales. La simulación implica reproducir la interfaz del objeto simulado. Al mismo tiempo que se programan las expectativas y respuestas de los originales. Es decir, son objetos que permiten probar si los valores que se les pasan son correctos y devolver una respuesta programada a estos. Se suelen utilizar cuando los objetos originales son difíciles de reproducir en entornos de prueba.
Por otro lado, los Stubs solamente guardan las respuestas. Aunque también pueden guardar información sobre las llamadas; como una pasarela de email que recuerda cuántos mensajes envió.
Implementación de Mocks en R
El paquete testthat
incorpora la posibilidad de implementar en las pruebas unitarias. Permitiendo probar operaciones que requieren componentes externos (como bases de datos o ficheros) sin la necesidad implementar estas en un entorno de simulación.
La ejecución de una prueba unitaria con un mock se realiza mediante la función with_mock
. En la llamada de esta función se ha de incluir las funciones que se desean sobrescribir, las pruebas y el entorno en el que se desean realizar las pruebas. Por ejemplo, de la documentación del paquete:
with_mock( all.equal = function(x, y, ...) TRUE, expect_equal(2 * 3, 4), .env = "base" )
En este ejemplo se sobrescribe la función all.equal
haciendo que devuelva siempre el valor cierto. Por lo que esta prueba no fallara al ser ejecutada a pesar de que la igualdad no sea cierta.
En un entorno de ejecución se pueden utilizar más de un mock y una prueba unitaria, de la documentación del paquete se puede ver este ejemplo:
with_mock( base::identical = function(x, y, ...) TRUE, base::all.equal = function(x, y, ...) TRUE, expect_equal(x <- 3 * 3, 6), expect_identical(x + 4, 9) )
donde no se ha indicado el entorno al ser indicado en la definición de la función a sobrescribir.
Finalmente, los stubs no esta incluidos en el paquete testthat
aunque se pueden conseguir mediante un sencillo truco, crear una función que implemente la prueba a partir de la entrada. Por ejemplo:
with_mock( print = function(x, y, ...) expect_that(x, equals(7)), print(7), .env = "base" )
donde se prueba que al método print()
se le pasa el valor 7.
Conclusiones
En esta entrada se ha realizado un repaso de las posibilidades que se tienen a la hora de escribir Stub y Mocks en R. Estas herramientas son claves a la hora de implementar pruebas de sistemas complejos que pueden depender de diferentes recursos.