Prueba de brecha entre unidad e integración: integración en las pruebas de integración de unidades pequeñas, componentes

9

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 Ay Bambos usan componentes C. Sin embargo, Ay Btienen requisitos ligeramente diferentes para, y hacer suposiciones ligeramente diferentes sobre C. Si soy el desarrollador de Acómo y dónde pruebo mis suposiciones C?

Obviamente, las pruebas unitarias Acon supuestos simulados Cson buenas para realizar pruebas Ade 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 Aestá en desarrollo, alterar las pruebas Ccon suposiciones en evolución Aserá excesivamente torpe. De hecho, Ael 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 Bdependerá Cde leer un archivo (entre otras cosas) y almacenar el contenido del archivo en el objeto pasado C. Al principio, todos los archivos que Cmaneja son pequeños y se pueden leer sincrónicamente sin un bloqueo significativo. Sin embargo, el desarrollador se Bda cuenta de que sus archivos se están volviendo enormes y necesita cambiar Ca una lectura asíncrona. Esto da como resultado un error de sincronización esporádica A, que todavía se supone que Cestá 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 Alas pruebas de la unidad s porque las Asuposiciones s se burlan. Sin embargo, podría ser fácilmente atrapado por una "mini" prueba de integración que ejerce de manera justa Ay 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 Ay Cpara 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?

mjhm
fuente
1
¿ha considerado el control de versiones de los módulos AC y utilizar alguna forma de gestión de dependencias?
miraculixx
1
@gnat Gracias por el consejo. Hice la pregunta menos vaga.
mjhm
@miraclixx Gracias por su sugerencia. ¿Podrías dar más detalles? Si te refieres a algo como blog.nodejitsu.com/package-dependencies-done-right , creo que esto resuelve un problema diferente del que estoy preguntando. Los componentes a los que me refiero son generalmente demasiado pequeños para la versión independiente como un módulo de nodo, por ejemplo, un archivo de componente Modelo o Controlador. Además, el control de versiones solo da pistas sobre la seguridad y las fuentes de fallas, en lugar de pruebas explícitas para problemas específicos.
mjhm

Respuestas:

6

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,

gbjbaanb
fuente
Sí, eso es lo que estoy pensando. Esto está más allá del alcance y el propósito de las pruebas unitarias. Desafortunadamente, no vivo en un mundo de software donde los componentes dependientes estén perfectamente diseñados, probados y documentados. Y las pocas pruebas de integración que tenemos generalmente son de extremo a extremo y manejadas por especialistas en control de calidad, en lugar de los desarrolladores de origen. Como puede suponer, hay problemas de gestión y organización en la mezcla.
mjhm
Supongo que tendrá que agregar sus propias pruebas de integración, pero llámelas pruebas unitarias, "estamos probando la unidad del módulo de inicio de sesión del cliente" a medida que ejecuta el pepino o el selenio.
gbjbaanb