¿Por qué utilizar la base de datos en memoria para las pruebas de integración?

18

Estoy realmente confundido cuando veo mucha implementación de base de datos en memoria utilizada para las pruebas, porque también escuché mucho de las mejores prácticas de pruebas de integración que el entorno que ejecuta la prueba debe parecerse lo más posible al entorno de producción, incluido el sistema operativo , biblioteca, motor de base de datos, etc.

¿Que me estoy perdiendo aqui?

dnang
fuente
Lo he visto mucho porque puede garantizar la consistencia de los datos mediante programación, además de que generalmente son razonablemente rápidos. Especialmente si su prueba es una prueba unitaria, quiere que sea un sistema cerrado. Desea que sus pruebas estén completamente incluidas en la prueba.
Plataforma
Es bueno que un desarrollador pueda obtener lo último de todo el código y ejecutar las pruebas, sin tener que configurar previamente una base de datos externa.
Jason Evans
1
Los aspectos que requieren un parecido cercano con el entorno de producción pertenecen a las pruebas de carga y pruebas de estrés, que en mi opinión deberían realizarse por separado de las pruebas unitarias (que, como criterio de compilación de código).
rwong

Respuestas:

19

En una situación típica de desarrollo de software, las pruebas se utilizan en dos puntos: durante el desarrollo y antes de mover el producto a lo largo de la cadena de desarrollo.

La primera situación, ejecutar pruebas durante el desarrollo, cumple objetivos a corto plazo: definir tareas (como en TDD: escribir una prueba fallida, luego hacerla pasar), evitar regresiones, asegurarse de que sus cambios no rompan nada más, etc. las pruebas deben ser extremadamente rápidas: idealmente, todo su conjunto de pruebas se ejecuta en menos de 5 segundos, y puede ejecutarlo en un bucle junto a su IDE o editor de texto mientras codifica. Cualquier regresión que introduzca aparecerá en cuestión de segundos. Las pruebas rápidas son más importantes en esta fase que detectar el 100% de las regresiones y errores, y dado que no es práctico (o absolutamente imposible) desarrollar copias exactas de los sistemas de producción, el esfuerzo requerido para lograr pruebas perfectas aquí no vale la pena. eso. El uso de bases de datos en memoria es una compensación: no son copias exactas del sistema de producción, pero ayudan a mantener las pruebas por debajo del límite de 5 segundos; si la elección es entre una configuración de base de datos ligeramente diferente para mis pruebas relacionadas con la base de datos, y ninguna prueba en absoluto, sé lo que elijo.

La segunda situación, mover el código a lo largo de la cadena de desarrollo, sin embargo, hace requerir pruebas exhaustivas. Dado que podemos (y deberíamos) automatizar esta parte del proceso de desarrollo, podemos permitirnos pruebas mucho más lentas, incluso si una prueba completa lleva horas, programar una compilación nocturna significa que siempre tenemos una imagen precisa de la base de código de ayer. Ahora es importante simular el entorno de producción con la mayor precisión posible, pero nos lo podemos permitir. Por lo tanto, no hacemos la compensación en la base de datos en memoria: instalamos la misma versión exacta del mismo DBMS que los sistemas de producción y, si es posible, la llenamos con datos de producción reales antes de que comience la prueba.

tdammers
fuente
6

Supongo que es una velocidad de compensación / coincidencia con el medio ambiente. Las pruebas deben ejecutarse con frecuencia, y eso significa que deben ser rápidas. Especialmente pruebas unitarias, que no deberían tomar más de unos segundos.

Las pruebas de integración se ejecutarán más lentamente, pero cuando son rápidas, puede ejecutarlas con más frecuencia. Por ejemplo, antes de cada commit. Por supuesto, no es tan completo como un entorno completo, pero al menos está probando la capa de mapeo, el SQL generado, cómo las partes se comunican entre sí, etc. En el caso de una base de datos costosa, también se asegura de no hacerlo ' No es necesario comprar una licencia para todos. Puede detectar más errores cubriendo el 90% del código con pruebas ejecutadas una vez por hora que cubriendo el 100% de las pruebas de código una vez por día o peor, semana.

Dicho esto, por supuesto, necesitas probar con la base de datos real y un entorno totalmente integrado. Es posible que no ejecute esas pruebas con tanta frecuencia, pero dado que su prueba anterior ya le dio confianza, todo lo que queda es un extraño error específico de la plataforma.

Laurent Bourgault-Roy
fuente
3

Para realizar pruebas simples, burlarse de la capa de acceso a la base de datos es perfectamente aceptable. Usted llama getName(), llama al DAO que se ha burlado y devuelve "John" para el primer nombre y "Smith" para el apellido, los ensambla y todo es perfecto. No es necesario probar la unidad de una base de datos allí

Las cosas se vuelven un poco más cuando la lógica se vuelve un poco más compleja. ¿Qué pasaría si tuviera un método "createOrUpdateUser (...)"? Si se burló de la base de datos, puede verificar que un método dado se haya llamado una vez con un determinado parámetro cuando el simulacro no devuelve objetos y se invoca un método diferente en la base de datos cuando devuelve un objeto existente. Esto comienza a llegar a esa línea difusa donde podría ser más fácil (especialmente si ya estaba allí) girar una base de datos especializada en memoria y probar ese código con datos preconfigurados.

En algún código real en el que trabajé (punto de venta), teníamos un resumeSuspededTransaction(...)método. Esto llevaría la transacción de la base de datos a un objeto (y sus componentes) y actualizaría la base de datos. Nos burlamos y un error acechaba en el código en algún lugar con la serialización y deserialización de los datos que van a la base de datos (cambiamos un tipo que se serializó de manera diferente en la base de datos).

El simulacro no nos mostró el error porque estaba devolviendo su camino feliz: serializar la transacción, almacenarla en el simulacro, deserializarla del simulacro, probar que son iguales. Sin embargo, cuando serializa un objeto con un cero inicial en la base de datos, los descarta y luego lo recombina de nuevo en una cadena sin los ceros. Detectamos el error sin la base de datos a través de la resolución de problemas (no fue tan difícil de detectar una vez que supimos que estaba allí).

Más tarde, pusimos una base de datos allí y nos dimos cuenta de que el error nunca habría superado esa prueba junit si hubiéramos ido a una base de datos en memoria.


En memoria las bases de datos tienen las ventajas:

  • se pueden girar rápidamente (sin necesidad de un DBA para configurar cuentas, tablas y demás) para realizar pruebas
  • los datos pueden preconfigurarse para esa prueba
  • la prueba no necesita preocuparse por revertir la prueba cuando haya terminado
  • cada prueba tiene su propia base de datos en memoria para que no tenga que preocuparse si dos pruebas se ejecutan simultáneamente
  • pueden ejecutarse en sistemas que no tienen conectividad a las bases de datos reales

fuente
1

Esto depende mucho del sistema de base de datos que esté utilizando. Cuando su sistema de base de datos le proporciona una alternativa en memoria que es casi 100% API y comportamiento compatible con una configuración de base de datos basada en disco (a excepción de la velocidad y la seguridad a prueba de fallas, por supuesto), entonces usar la variante en memoria obviamente está bien .

Sin embargo, si su sistema de base de datos tiene diferencias significativas entre la configuración en memoria y el uso sin memoria, tiene razón: en este caso, las pruebas de integración tienen un mayor riesgo de sombrear un error. Pero incluso entonces, es posible que pueda "abstraer esas diferencias" por sí mismo, dado que conoce bien su sistema de base de datos y las diferencias.

Doc Brown
fuente
1

En palabras simples:

La burla de partes importantes de la arquitectura está bien (y es imprescindible) para las pruebas unitarias .

Pero para las pruebas de integración, estoy totalmente de acuerdo con usted. La burla no debe hacerse y debe proporcionarse un entorno lo más similar posible al real.

Después de todo, las pruebas de integración consisten en probar cómo se comportan juntas las diferentes partes de la arquitectura.

Tulains Córdova
fuente