Bases de datos y pruebas de unidad / integración

25

He tenido una discusión con alguien sobre las pruebas de unidad / integración con aplicaciones web y tengo un desacuerdo sobre 1 idea central. El problema es que la persona con la que estoy hablando piensa que la base de datos de la que funciona la prueba de la unidad debe tener datos previamente completados y creo que debe estar completamente vacía antes y después de que se ejecuten las pruebas.

Mi preocupación con los datos rellenados previamente en la base de datos es que no hay forma de garantizar que los datos se mantengan en buen estado. Las pruebas en sí mismas van a crear, eliminar y modificar datos en la base de datos, por lo que realmente no veo cómo tener datos en la base de datos antes de comenzar las pruebas es algo bueno.

Parece que la mejor manera de probar la funcionalidad de la base de datos sería tener las siguientes configuraciones:

  1. En una fase de "configuración" antes de que se ejecute la prueba, primero trunca todas las tablas de la base de datos
  2. Luego inserta todos los datos necesarios para los casos de prueba que está a punto de ejecutar
  3. Luego ejecuta y valida los casos de prueba
  4. Luego, en una fase de "desmontaje", una vez más trunca todas las tablas de la base de datos

No veo otra mejor manera de garantizar que los datos con los que está probando sean una buena prueba comprobable.

¿Me estoy perdiendo de algo? ¿No es esta la mejor manera de probar la funcionalidad relacionada con la base de datos? ¿Hay algún beneficio en tener una base de datos pre-poblada que siempre existe en la base de datos (incluso antes de comenzar las pruebas o después de que las pruebas se hayan realizado)? Cualquier ayuda en ideas para explicar mi proceso de manera diferente para comprender mejor mi punto de vista también sería genial (es decir, si mi punto tiene méritos).

ryanzec
fuente
ver también: Técnicas de prueba de software
mosquito

Respuestas:

21

Para mí, las pruebas unitarias no deben tratar con la base de datos, las pruebas de integración tratan con la base de datos.

En la práctica, las pruebas de integración que tratan con la base de datos deben tener una base de datos vacía con un enfoque de desgarre y desgarre, el uso de un enfoque basado en transacciones es un buen camino a seguir (es decir, crear una transacción en la configuración y deshacer en desmantelamiento).

Lo que su amigo parece querer hacer es probar desde un punto de vista de 'regresión', es decir, tener datos reales allí y ver cómo reacciona el sistema, después de todo, ningún sistema es perfecto y, por lo general, puede haber datos incorrectos en algún lugar que proporcionen Algunas peculiaridades de su modelo de dominio.

Sus mejores prácticas son el camino a seguir, y lo que tiendo a hacer es si encuentro un escenario para datos incorrectos, escribo una prueba de integración con una configuración y derribo con ese escenario exacto.

Nicholas Mayne
fuente
Solo estoy seguro de cuál es la diferencia entre las pruebas unitarias y las pruebas de integración, además escuché que la unidad debería usar datos simulados y la integración debería usar una base de datos (comenzó otro hilo programmers.stackexchange.com/questions/101300/... para descubrir la diferencia ) Aparte de eso, todo lo que dices parece estar en línea con lo que estoy pensando.
ryanzec
No hay problema, he agregado más información a su otra respuesta
Nicholas Mayne
1
¿Por qué no puedes probar la unidad de base de datos? Si coloca su SQL en procedimientos almacenados, puede realizar una prueba unitaria con datos definidos por la prueba, y de repente todo es fácil. Esto es definitivamente una buena práctica más personas deben seguir, ver lo que dice MS
gbjbaanb
1
integration tests- ¿Qué quieres decir? Como mencioné, los módulos que utilizan bases de datos pueden y deben probarse con pruebas unitarias. La base de datos puede ser burlada manualmente o reemplazada con implementación en memoria
hellboy
6

Si sus pruebas dependen de la base de datos, entonces creo que es más importante que los datos que le interesan estén en un estado conocido para sus pruebas, en lugar de que la base de datos esté vacía. Una de las medidas de las buenas pruebas es que cada prueba debe fallar por una razón y ninguna otra prueba debe fallar por la misma razón.

Por lo tanto, si sus pruebas se preocupan por el estado de los datos, obtenga los datos en ese estado conocido y devuelva los datos a ese estado después de que se hayan ejecutado sus pruebas, para que sus pruebas sean reproducibles.

Si puede desacoplar sus pruebas del estado de los datos burlándose, eso también sería algo bueno. Menciona que está haciendo pruebas de unidad / integración, pero, por supuesto, esas dos cosas deben considerarse por separado. Si es posible, las pruebas unitarias deben desacoplarse de la base de datos y las pruebas de integración deben probarse con la base de datos en un estado conocido.

Paddyslacker
fuente
2

Bueno, veo un beneficio en tener una base de datos prepoblada: no tiene que escribir el código que insertará los datos que necesita, ya que está allí. De lo contrario, solo hay inconvenientes. ¿Quizás alguien modificó los datos de prueba en la base de datos? ¿Quizás alguien intentó actualizar los datos? Pero lo peor es tener un caso de prueba que estropea la base de datos ... Terminas recreando la base de datos completa manualmente varias veces.

Tienes razón en cómo se deben escribir las pruebas, excepto que no truncaría nada:

  • fase de configuración: obtenga una conexión a la base de datos e inserte los datos
  • fase de ejecución
  • fase de desmontaje: eliminar los datos insertados (truncar)

Ahora, ese escenario es ideal para pruebas unitarias. Cuando uno necesita datos para las pruebas de unidad e integración, descubrí que una gran fase de configuración común a todos los casos de prueba (reagrupamos todos los "insertos" en un método estático) también puede funcionar muy bien. Es como un punto medio entre su idea y la idea de su amigo. El único inconveniente es que debe tener mucho cuidado al agregar algunos datos nuevos para no romper los casos de prueba existentes (pero si agrega como dos o tres filas por tabla como lo hicimos nosotros, no debería ser un problema)

Jalayn
fuente
¿No preferiría crear las partes de la base de datos necesarias para la prueba antes que que alguien modifique accidentalmente los datos de una manera que cause una falla? Tener que asegurarse de que los datos sean correctos cuando falla una prueba parece algo que se puede evitar.
ryanzec
1
La gran fase de configuración que inserta datos útiles para diferentes casos de prueba solo puede ser útil para pruebas de integración en las que necesita verificar que diferentes partes de la aplicación trabajen juntas. Puede valer la pena tener este gran conjunto común de "inserciones" porque probablemente necesitará algunas de ellas para otras pruebas de integración. De lo contrario, si estamos hablando solo de pruebas unitarias puras, estoy absolutamente a favor de tener un conjunto de datos para insertar para cada caso de prueba.
Jalayn
1

Creo que necesita limitar un ejemplo con su colega y descubrir qué significan exactamente. Ambos pueden estar en la misma página.

Ejemplo: tabla de transacciones de cuenta corriente

  1. ¿No le gustaría probar ver esta tabla para un usuario / cuenta sin transacciones?
  2. Pruebe agregar el primer registro y vea si puede crear un equilibrio.
  3. Cree registros cuando ya existan registros y verifique el saldo corriente y cualquier otra regla comercial.
  4. Ver tabla con registros existentes y todos los demás CRUD.

Si logra esto ejecutando los pasos 1 y 2 o comenzando con una base de datos que ya está en este estado (¿restaurar una copia de seguridad?) No estoy seguro de que sea importante. Su idea de enviarme un script hace que sea más fácil administrar los cambios que necesita (por ejemplo, si olvidó crear una cuenta de administrador y la necesita para un nuevo usuario). Los archivos de script son más fáciles de poner en el control de origen que algunos archivos de respaldo. Esto también se ve afectado por si distribuye o no esta aplicación.

JeffO
fuente
0

Para dibujar aspectos de algunas respuestas juntas y agregar mi 2p ...

Nota: mis comentarios se relacionan particularmente con las pruebas de bases de datos y no con las pruebas de IU (aunque obviamente se aplica algo similar)

Las bases de datos necesitan pruebas tanto como las aplicaciones front-end, pero tienden a ser probadas en base a '¿funciona con el front-end?' o '¿los informes producen el resultado correcto?', que en mi opinión está probando muy tarde en el proceso de desarrollo de la base de datos y no es muy robusto.

Tenemos una serie de clientes que utilizan pruebas de unidad / integración / sistema para su base de datos del almacén de datos además de la UAT / performance / et al habitual. pruebas Encuentran que con una integración continua y pruebas automatizadas, resuelven muchos problemas antes de llegar a UAT tradicional, lo que ahorra tiempo en UAT y aumenta las posibilidades de éxito de UAT.

Estoy seguro de que la mayoría estaría de acuerdo en que se debe aplicar un rigor similar a las pruebas de bases de datos como a las pruebas de front end o de informe.

La clave con las pruebas es probar pequeñas entidades simples, asegurando su corrección, antes de proceder a combinaciones complejas de entidades, asegurando su corrección antes de expandirse al sistema más amplio.

Entonces, dando un poco de contexto a mi respuesta ...

Examen de la unidad

  • tiene un enfoque de prueba para demostrar que la unidad funciona, por ejemplo, una tabla, vista, función, procedimiento almacenado
  • debería 'tropezar' las interfaces para eliminar dependencias externas
  • proporcionará sus propios datos. Necesita un estado inicial conocido de los datos, por lo que si existe la posibilidad de que exista una prueba previa de datos, entonces deben ocurrir truncamientos / eliminaciones antes de la población
  • correrá idealmente en su propio contexto de ejecución
  • se borrará después de sí mismo y eliminará los datos que utilizó; esto solo es importante cuando no se usan trozos.

Las ventajas de hacer esto son que está eliminando todas las dependencias externas de la prueba y está realizando la menor cantidad de pruebas para demostrar la corrección. Obviamente, estas pruebas no se pueden ejecutar en la base de datos de producción. Es posible que haya varios tipos de pruebas que realizará, según el tipo de unidad, que incluyen:

  • verificación de esquema, algunos podrían llamar a esto una prueba de "contrato de datos"
  • valores de columna que pasan por
  • El ejercicio de rutas lógicas con diferentes valores de datos para funciones, procedimientos, vistas, columnas calculadas
  • prueba de caso límite: NULL, datos incorrectos, números negativos, valores que son demasiado grandes

(Unidad) Pruebas de integración

Esta publicación SE me pareció útil al hablar sobre varios tipos de pruebas.

  • tiene el enfoque de prueba para demostrar que las unidades se integran juntas
  • realizado en varias unidades juntas
  • debería 'tropezar' las interfaces para eliminar dependencias externas
  • proporcionará sus propios datos, para eliminar los efectos de influencias externas de datos
  • correrá idealmente en su propio contexto de ejecución
  • se borrará después de sí mismo y eliminará los datos creados; esto solo es importante cuando no se usan trozos.

Al pasar de las pruebas unitarias a estas pruebas de integración, a menudo habrá un poco más de datos, para probar una variedad más amplia de casos de prueba. Obviamente, estas pruebas no se pueden ejecutar en la base de datos de producción.

Esto luego pasa a las Pruebas del sistema , Pruebas de integración del sistema (también conocidas como pruebas de extremo a extremo 2), con volúmenes de datos crecientes y un alcance creciente. Todas estas pruebas deberían formar parte de un marco de pruebas de regresión. Los usuarios pueden elegir algunas de estas pruebas para realizarlas como parte de la UAT, pero UAT son las pruebas definidas por los usuarios , no según lo definido por TI, ¡un problema común!

Entonces, ahora que he dado un poco de contexto, para responder a sus preguntas reales

  • la prepoblación de datos para pruebas de unidad e integración puede causar errores de prueba espurios y debe evitarse.
  • La única forma de garantizar pruebas consistentes es no hacer suposiciones sobre los datos de origen y controlarlos rigurosamente.
  • un contexto de ejecución de prueba separado es importante, para garantizar que un probador no entre en conflicto con otro probador que realice las mismas pruebas en una rama diferente del código de la base de datos controlada por la fuente.
Marcus D
fuente
-3

Francamente, creo que si realiza pruebas unitarias sin una base de datos aproximadamente del mismo tamaño que la base de datos de producción existente, tendrá muchas cosas que pasan las pruebas y fallan en la producción por rendimiento. Por supuesto, también estoy en contra de que las personas desarrollen una pequeña base de datos local por este motivo.

Y si el código es específico de datos, ¿cómo puede probarlo efectivamente sin datos? Echará de menos ver si las consultas arrojaron los resultados correctos. ¿Por qué querrías considerar probar con una base de datos vacía? Todo lo que te dice es si la sintaxis es correcta, no si la consulta es correcta. Eso me parece miope. He visto demasiadas cosas que ejecutan y pasan pruebas que son categóricamente incorrectas. ¿No quieres encontrar eso en las pruebas unitarias? Hago.

HLGEM
fuente
No estoy sugiriendo que se ejecute en una base de datos vacía, si ve el paso 2, tengo "Luego inserta todos los datos necesarios para los casos de prueba que está a punto de ejecutar". Sobre el problema de rendimiento, no creo que para eso estén las pruebas unitarias, sino más pruebas de carga. Unidad de prueba para mí para probar para asegurarse de que lo lógico en su código funcione. si la lógica funciona, funcionará para 1 registro o 100,000,000,000 registros de los mismos datos básicos (pensé que sería mucho más lento).
ryanzec
Las consultas a la base de datos no son solo lógicas y cuanto antes descubra que no funcionará en producción, mejor. Lo que funciona para 1 registro a menudo excederá el tiempo de espera en la producción y la prueba de la unidad debe mostrarlo tan pronto como sea posible.
HLGEM
Las pruebas de unidad e integración son de funcionalidad y no de rendimiento, por lo que puede realizar pruebas con pequeñas cantidades de datos
usuario151019
Las pruebas unitarias nunca deben usar una base de datos; las pruebas de integración usan bases de datos.
Nicholas Mayne
1
De lo que realmente estás hablando es de pruebas de carga. Si tuviera un conjunto de pruebas de aceptación y las conectara a una herramienta de prueba de carga, entonces podría lograr el efecto deseado.
Nicholas Mayne