Pruebas de integración y bases de datos no transaccionales

8

Un problema que creo que voy a encontrar con mis pruebas de integración es tener varias pruebas para acceder a la misma base de datos. Si bien esto no es un problema ahora, sé que tenemos varias aplicaciones aquí que acceden a la misma base de datos y solo estoy tratando de pensar en una forma de prevenir este problema antes de que suceda.

Una idea que he visto mucho es usar transacciones. En el inicio, inicia una transacción y luego, en el desmontaje, se deshace la transacción. Esto significa que múltiples pruebas que acceden a las mismas tablas de la base de datos y no se afectarán entre sí, lo que es excelente. El problema que tengo es que en mi caso, el 85-95% de las tablas con las que estoy trabajando en MySQL son MyISAM que no admiten transacciones.

¿Hay alguna forma de evitar los motores de almacenamiento que no admiten transacciones pero que permiten que múltiples pruebas accedan a las mismas tablas sin que se afecten entre sí? Por lo que he oído, el marco de pruebas de Ruby on Rails utiliza transacciones de esta manera, ¿cómo solucionan este problema (o lo hacen)?

    
pregunta ryanzec 16.08.2011 - 20:37

3 respuestas

3

En mi empresa, hubo ese debate: la persistencia es un gran problema para las pruebas.

Hay algunos hacks que te llevarán hasta la mitad. Decidimos no perder nuestro tiempo con ellos:

  • utilizando Transacciones que restituya . Eso falla como:
    • Algunas veces abre una transacción aislada (dentro de una más general), por lo que se cerró antes de que el código de prueba pueda controlarla
    • No puedes probar tu persistencia real. (Lo que sucede cuando una prueba cierra una transacción y ejecuta una consulta compleja afectada por esos datos en una transacción diferente; o guarda los datos y luego los vuelve a cargar).
    • No puede probar su código completamente (solo las capas por debajo del nivel de transacción; no es lo suficientemente bueno si considera los inconvenientes de las pruebas de integración).
  • utilizando una Base de datos nueva y limpia para cada prueba . Eso también falla como:
    • nuestro conjunto de pruebas pronto llegará a unos pocos miles de pruebas (tenemos grandes equipos). La configuración de una nueva base de datos requiere en el mejor de los minutos (ya que tenemos muchos catálogos y parámetros que forman parte de cada versión). Nuestro conjunto de pruebas tardará unos meses en finalizar, y solo podemos esperar unos días.
    • necesitaríamos una instancia de base de datos específica para cada desarrollador, o cada máquina, y tendríamos una política para lanzar solo una prueba a la vez. Necesitamos usar Oracle 11 para verificar que nuestras consultas estén bien, eso sería demasiado costoso (licencias de Oracle).
  • limpiando cuidadosamente después de cada prueba (los marcos de prueba proporcionan enlaces para ejecutar el código después de una prueba). Eso falla como:
    • es muy costoso mantener una coincidencia perfecta entre el código que does y la prueba que undoes . Tan pronto como la coincidencia no es perfecta, los síntomas no son claros, una prueba puede fallar y luego de unos cientos de líneas; o una prueba que debe fallar podría pasar por error.
    • siempre hay casos en los que la limpieza no es correcta (¿falla la máquina o el software?). Eso deja un estado desconocido para ejecuciones posteriores.
    • cuando una prueba muestra un error, el estado de la base de datos sería una información esencial, pero se perdería (porque limpiamos antes de la siguiente prueba, para finalizar el conjunto de pruebas y mostrarle al desarrollador una información completa). / li>

Así que pasamos a una política que sabíamos que era válida:

  • haga Pruebas unitarias automáticas para nuestros requisitos :
    • si es necesario, accesos de base de datos simulados (pero generalmente no necesitamos JMock, podría explicar nuestro diseño si se me solicita).
    • las pruebas se ejecutan con una tasa de más de 100 por segundo
    • las pruebas son rápidas de escribir, cortas y claras de leer.
    • las pruebas no dependen de ningún estado persistente, por lo que están completamente aisladas unas de otras de forma natural (no se necesita un mecanismo complejo)
  • pruebe integrándose con la base de datos por separado (es decir, solicitud por solicitud, no integrada con la lógica de la aplicación).
    • consideramos automatizar esa tarea, pero parecía demasiado costoso (ver la parte anterior de mi publicación)
    • por lo que mantuvimos estas pruebas manuales: se espera que cada desarrollador que modifique una consulta vuelva a probar la base de datos (que suele ser parte de sus pruebas de extremo a extremo a través de la interfaz de usuario).
respondido por el KLE 29.08.2011 - 22:39
2

Incluso si no tiene "transacciones", en el sentido de T-SQL, debe esforzarse por hacer que sus transacciones (en el sentido general del término) sean atómicas. Las pruebas no deben depender entre sí y deben ser reversibles. Si no tiene ningún retroceso oficial o el alcance de la transacción, es posible que desee realizar el suyo propio. Por ejemplo, puede hacer que sus pruebas de unidad realicen una limpieza, donde eliminen todos los registros que se crearon en la prueba.

    
respondido por el Morgan Herlocker 16.08.2011 - 20:51
0

Simplemente haga que cada usuario o cada ejecución anule la base de datos utilizada. Eso es lo que hacemos en el trabajo. Entonces, nunca tendrá problemas con 2 pruebas simultáneas que interfieren entre sí.

Tenemos cada ejecución de prueba que construye la base de datos con migraciones, llena la base de datos con accesorios y luego la vuelve a arrancar al final.

Si el DBMS admite transacciones, lo utilizamos como una optimización para la configuración inicial y el desmontaje. Son opcionales, aunque tu prueba puede durar un poco sin ella. Como siempre YYMV.

Sin problemas, no hay problema.

    
respondido por el dietbuddha 30.08.2011 - 00:07

Lea otras preguntas en las etiquetas