¿Qué estoy probando y cuáles son mis dependencias en testing?

Estos días he estado preparando una serie de posts sobre pruebas unitarias y en concreto, algo que parece que a todos nos trae de cabeza: los mocks, stubs…es decir, cómo hacer realmente una prueba unitaria sin que se convierta en una prueba de integración y entender qué es eso de “mockear”.

Por cierto, si no sabes que es una prueba unitaria, de integración, recuerda el post de ¿Pruebas de integración, funcionales, de carga…? ¡Qué jaleo! ¿Qué diferencias hay?.

A la hora de enfocar ese post, quería haber empezado refrescando qué es una prueba unitaria. En una prueba unitaria probamos una unidad de software por si sola (normalmente una clase, objeto, etc.). Aquí no me interesa saber que la interacción de esa unidad con otro método o con otro objeto funciona bien; solo quiero probar que recibiendo los datos necesarios de alguna manera, la unidad se comporta de la forma en la que se espera.
Por lo tanto, lo que no forme parte de esa unidad es un candidato a ser simulado, “mockeado” (en los próximos posts veremos que esto es un concepto más amplio y hay distintos tipos de simulaciones con distintos nombres, no solo mocks), ya que no me interesa, solo quiero saber que esa unidad funciona bien.
En este punto me quedé pensando: vale, creo que aquí, en la propia definición, empiezan a aparecer las primeras dudas de la gente que quiere aprender a hacer pruebas unitarias y mocks: ¿cuál podría ser es esa unidad que se prueba? ¿y cuáles son las dependencias que hay que simular?
Por eso, en lugar de empezar a hablar de mocks, stubs y pruebas unitarias de lleno, quiero empezar esta serie de posts con un post que hable de una cosa básica de testing, que servirá para poner en contexto a los siguientes:
¿Qué probamos y cuáles son mis dependencias en testing? O de forma más técnica, que es un SUT (System under test) y DOCs (Depended On Component).
He de decir que esta terminología fue introducida por Gerard Meszaros, en su libro xUnit Test Patterns.
Según el tipo de prueba, el sistema bajo prueba y los componentes en los que dependes serán distintos. Y tener identificados estos aspectos a la hora de diseñar una prueba es muy importante para hacerla bien, hasta en una prueba unitaria.
¡Así que vamos allá!

¿Qué es SUT (System under test)?

Es aquello que se está probando. En función del tipo de prueba, el sistema bajo prueba tendrá una granularidad distinta (métodos, una clase, una aplicación entera, un componente, etc.)
En un test hay un único sistema bajo prueba, un único SUT, es decir, que el foco de mi test es uno: probar cómo se comporta una clase concreta, algo del sistema, etc.

¿Qué son DOCs (Depended On Component)?

Es lo que necesita el SUT, es lo que necesita lo estamos probando para poder funcionar, para hacer lo que tiene que hacer, los elementos en los que depende el SUT.
Normalmente ambos componentes (SUT y DOCs) tienen la misma granularidad: por ejemplo, si estamos testeando una clase en concreto, dicha clase dependerá de otras clases; si es un componente, dependerá de otros componentes, etc.
Lo que estemos probando (SUT) podrá depender de uno o más elementos. El número de elementos en los que dependa lo que estemos probando (clase, sistema, componente, etc.) puede ser un indicador de lo bien diseñado que está el propio SUT: si depende de muchos componentes, probablemente el sistema que estamos probando tiene demasiada responsabilidad y deberíamos desacoplarlo un poco más.

¿Puedes ponerme ejemplos de qué sistemas prueban cada tipo de prueba y qué dependencias tienen?

Tipo de prueba*Ejemplo de aquello que podemos probar (SUT)Ejemplo de dependencia (DOC)
Prueba unitariaClase UsuarioClase que implementa el sistema de mail
Prueba de integraciónMódulo de búsqueda (en este caso sería un ejemplo de prueba de integración porque el módulo de búsqueda incluye varias clases y métodos y queremos probar la integración del módulo con la base de datos)Base de datos
Prueba end-to-endToda la aplicaciónSistemas externos a los que se conecta, servicios web externos, etc.

*Menos las pruebas unitarias que son solo automáticas, el resto de pruebas pueden ser manuales o automáticas.
Los sistemas bajo prueba, el foco del test, aquello que estamos probando, no se simula, es real. No se hacen mocks.
Los candidatos a simular son los DOCs, los componentes en los que depende el sistema que estamos probando.
Normalmente, se simulan los DOCs cuando hacemos pruebas unitarias. En el ejemplo de la tabla que puse, haría una prueba unitaria de la clase Usuario si simulara el sistema de mail (quiero probar solo la clase Usuario y no su interacción con el sistema de mail).
En el resto de pruebas también se pueden hacer simulaciones, mocks. Normalmente se hacen si interactuar con los otros componentes es muy complicado, lento, etc.

Cuando vamos a hacer una prueba ¿cómo se inicializa lo que estamos probando (SUT)? ¿y las dependencias (DOCs)?

Nuevamente esto depende del tipo de prueba. Si estamos haciendo una prueba unitaria, normalmente primero simularemos o inicializaremos los DOCs (por ejemplo, instanciaremos las clases necesarias, con los datos y argumentos necesarios), ya que es muy probable que el sistema que estemos probando (SUT) necesite que dichos componentes estén inicializados para funcionar.
En el caso de una prueba de integración, puede que el SUT y los DOCs se inicialicen a través del framework que uses, inyectando dependencias, etc.
O si hablamos de hacer una prueba de integración con una base de datos, configuraremos los datos que necesitamos para la prueba a través de scripts, antes de ejecutar la prueba automática, con herramientas como DBUnit (podemos insertar datos en la base de datos antes de iniciar el test y luego borrarlos al ejecutar el test para garantizar el estado limpio de la base de datos), etc.
—–
Ahora que ya hemos visto cuál es el foco prueba de cada tipo de prueba y cuáles podrían ser las dependencias, en los próximos posts entraremos al mundo de las pruebas unitarias, tests doubles, mocks, stubs, etc. 🙂

jgarzas

Ph.D. en informática, Postdoctorado en la Carnegie Mellon (EE.UU) e Ingeniero en Informática.

Primera vez que me tocó hacer una gestión Ágil en una empresa... año 2001. Desde entonces he trabajado en, o para, más de 90. Y he formado a más de 2000 alumnos.

También soy profe de la Universidad Rey Juan Carlos.

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *