En las últimas semanas, he estado reflexionando e investigando cómo llenar un vacío en nuestra metodología de prueba. En términos simplificados, las pruebas unitarias son demasiado pequeñas y las pruebas de integración tradicionales son demasiado grandes.
Un escenario frecuente surge donde A
y B
ambos usan componentes C
. Sin embargo, A
y B
tienen requisitos ligeramente diferentes para, y hacer suposiciones ligeramente diferentes sobre C
. Si soy el desarrollador de A
cómo y dónde pruebo mis suposiciones C
?
Obviamente, las pruebas unitarias A
con supuestos simulados C
son buenas para realizar pruebas A
de forma aislada, pero no prueba las suposiciones en sí mismas.
Otra posibilidad es agregar pruebas unitarias para C
. Sin embargo, esto no es ideal porque, mientras A
está en desarrollo, alterar las pruebas C
con suposiciones en evolución A
será excesivamente torpe. De hecho, A
el desarrollador puede no tener acceso adecuado a las pruebas unitarias de C
(por ejemplo, una biblioteca externa).
Para enmarcar esto con un ejemplo más concreto: suponga que se trata de una aplicación de nodo. A
, y B
dependerá C
de leer un archivo (entre otras cosas) y almacenar el contenido del archivo en el objeto pasado C
. Al principio, todos los archivos que C
maneja son pequeños y se pueden leer sincrónicamente sin un bloqueo significativo. Sin embargo, el desarrollador se B
da cuenta de que sus archivos se están volviendo enormes y necesita cambiar C
a una lectura asíncrona. Esto da como resultado un error de sincronización esporádica A
, que todavía se supone que C
está leyendo los archivos sincrónicamente.
Este es el tipo de error que es notoriamente difícil de rastrear desde pruebas de integración completas, y puede no quedar atrapado en las pruebas de integración. Tampoco queda atrapado por A
las pruebas de la unidad s porque las A
suposiciones s se burlan. Sin embargo, podría ser fácilmente atrapado por una "mini" prueba de integración que ejerce de manera justa A
y C
.
Solo he encontrado algunas referencias a este tipo de pruebas. Integración en el intestino , pruebas de integración de componentes , Unidad de Integración de pruebas. También se relaciona algo con la dirección de prueba de BDD en lugar de la prueba de unidad formal de TDD.
¿Cómo lleno este vacío de prueba? Específicamente, ¿dónde pongo tales pruebas? ¿Cómo me burlo de las entradas A
y C
para las pruebas de integración "mini"? ¿Y cuánto esfuerzo se debe poner en separar las preocupaciones de las pruebas entre estas pruebas y las pruebas unitarias? ¿O hay una mejor manera de llenar el vacío de prueba?
Respuestas:
Me parece que tiene un problema fundamental con sus componentes.
C debe hacer lo que C necesita hacer, y ser probado, documentado y diseñado para hacer precisamente eso. Cuando tienes una situación en la que C está diseñada para "hacer lo que B quiere", tienes una relación abusiva, que se vuelve muy clara cuando llega A y quiere que C haga algo ligeramente diferente.
Lo que no debe hacer es probar la unidad C en el contexto de A, y especialmente no A en el contexto de C: prueba A independientemente y proporciona los resultados de una C burlada a A. Si la versión del mundo real de C no proporciona los mismos resultados, entonces tiene un error o falla de diseño en C que se detectará cuando realice sus grandes pruebas de integración. La prueba de la unidad siempre ha sido así: no puede probar una unidad probando otra unidad al mismo tiempo. Las pruebas unitarias simplemente no están diseñadas para hacer eso.
Las pruebas de integración no tienen que ser "el programa completo", aunque con frecuencia se configuran de esa manera. Pueden ser un equipo de prueba que ejecuta A y C juntos sin ejecutar el resto del programa (o tan poco como pueda). En este punto, no puedo aconsejar más, ya que depende de lo que hacen estos componentes y cómo interactúan con el resto de su programa, pero generalmente es el caso de que pueda escribir un equipo de prueba que proporcione cobertura de prueba de ambos componentes. Ya sea que valga la pena hacer eso, o si es más eficiente probar la integración de todo el programa como uno solo (incluso si ejecuta un subconjunto de las pruebas de integración) es algo que solo usted puede responder. La mayoría de las pruebas de integración se componen de muchas secciones, por lo que es de esperar que pueda ejecutar solo aquellas relevantes para estos 2 componentes (y si no,
fuente