Prueba unitaria de procedimientos almacenados


44

He estado considerando esto durante bastante tiempo.

La pregunta básica es: ¿cómo probar los procedimientos almacenados?

Veo que puedo configurar pruebas unitarias con relativa facilidad para funciones en el sentido clásico (quiero decir que obtienen cero o más argumentos y devuelven un valor). Pero si considero un ejemplo de la vida real de un procedimiento aparentemente simple que inserta una fila en algún lugar, con algunos desencadenantes haciendo esto y aquello antes o después de la inserción, incluso definir los límites de una 'unidad' es bastante difícil. ¿Debo probar solo el INSERTsí mismo? Eso es bastante sencillo, creo, con un valor relativamente bajo. ¿Debo probar el resultado de toda la cadena de eventos? Además de la pregunta de si se trata de una prueba unitaria o no, diseñar una prueba adecuada puede ser un trabajo bastante arduo con muchos signos de interrogación adicionales que surgen en el camino.

Y luego viene el problema de cambiar constantemente los datos. En el caso de que UPDATEafecte más que unas pocas filas, cada fila potencialmente afectada debe incluirse de alguna manera en los casos de prueba. Más dificultades con DELETEs y así sucesivamente.

Entonces, ¿cómo prueba la unidad sus procedimientos almacenados? ¿Hay un umbral en la complejidad donde se vuelve completamente desesperado? ¿Qué recursos se necesitan para el mantenimiento?

EDITAR Una pequeña pregunta más, basada en la respuesta de AlexKuznetsov: ¿O hay un umbral bajo el cual es completamente inútil?

Respuestas:


32

Hemos estado haciendo esto durante casi cinco años, y creemos que probar modificaciones explícitamente es definitivamente factible, pero es bastante lento. Además, no podemos ejecutar fácilmente tales pruebas simultáneamente desde varias conexiones, a menos que usemos bases de datos separadas. En cambio, debemos probar las modificaciones implícitamente: las usamos para generar al menos algunos de los datos de prueba y verificar que nuestras selecciones devuelvan los resultados esperados.

He escrito un artículo titulado Cerrar esos agujeros: lecciones aprendidas de Unit Testing T-SQL , así como algunas publicaciones de blog

Con respecto a su pregunta "¿Existe un umbral en la complejidad donde se vuelve completamente desesperado?", Los módulos complejos necesitan pruebas mucho más que las simples.

Para simplificar el mantenimiento, generamos los resultados esperados y los almacenamos en archivos separados, lo que hace una gran diferencia.


15

Sí, debe probar toda la cadena de eventos como una unidad. Entonces, en su ejemplo con un procedimiento que se inserta en una tabla y hace que se disparen varios disparadores, debe escribir pruebas unitarias que evalúen el procedimiento para varias entradas. Cada prueba unitaria debe pasar o fallar dependiendo de si devuelve los valores correctos, cambia el estado de las tablas correctamente, crea el correo electrónico correcto e incluso envía los paquetes de red correctos si está diseñado para hacer tal cosa. En resumen, todos los efectos que tenga la unidad deben ser verificados.

Tiene razón, el diseño de las pruebas unitarias requiere algo de trabajo, pero la mayor parte de ese trabajo debe hacerse para probar manualmente la unidad, solo está guardando el trabajo requerido para probar la unidad, de modo que cuando se realice un cambio en el futuro, la prueba puede ser igual de completo y significativamente más fácil.

Cambiar los datos hace que las pruebas sean más difíciles, pero no hace que las pruebas sean menos importantes y en realidad aumenta el valor de las pruebas unitarias, ya que la mayoría de las dificultades solo deben pensarse una vez en lugar de cada vez que se realiza un cambio en la unidad. Los conjuntos de datos guardados, las inserciones / actualizaciones / eliminaciones que forman parte de la configuración / desmontaje y la operación de alcance limitado se pueden utilizar para facilitar esto. Como la pregunta no es específica de la base de datos, los detalles variarán.

No existe un umbral de complejidad en el extremo superior o inferior que le impida realizar pruebas o pruebas unitarias. Considere estas preguntas:

  1. ¿Siempre escribes código libre de errores?
  2. ¿Las unidades pequeñas siempre están libres de errores?
  3. ¿Está bien que una unidad grande tenga un error?
  4. ¿Cuántos errores se necesitan para causar un desastre?

Supongamos que comienza un nuevo trabajo y tiene la tarea de hacer una optimización para una pequeña función utilizada en muchos lugares. Toda la solicitud fue escrita y mantenida por un empleado que nadie recuerda. Las unidades tienen documentación que describe el comportamiento normal esperado, pero poco más. ¿Cuál de estos preferirías encontrar?

  • No hay pruebas unitarias en ninguna parte de la aplicación. Después de realizar el cambio, puede hacer algunas pruebas manuales con la unidad en sí para asegurarse de que aún devuelve los valores esperados en la documentación. Luego puede implementarlo en producción, cruzar los dedos y esperar que funcione (después de todo, siempre escribe código libre de errores y una optimización en una unidad nunca podría afectar a otra) o pasar una gran cantidad de tiempo aprendiendo cómo funciona toda la aplicación funciona para que pueda probar manualmente cada unidad directa o indirectamente efectuada.
  • Pruebas unitarias en toda la aplicación que se ejecutan automáticamente a diario o bajo demanda. Verifican no solo los valores de entrada normales y su respuesta esperada, sino también los valores anormales y las excepciones esperadas que se generan. Realiza el cambio y ejecuta el conjunto de pruebas de unidad para la aplicación de inmediato, ya que otras tres unidades ya no devuelven los resultados esperados. Dos de ellos son benignos, por lo que debe ajustar las pruebas unitarias para dar cuenta de eso. El tercero requiere otro pequeño ajuste y una pequeña prueba de unidad nueva. Después de realizar los cambios, todo el conjunto de pruebas tiene éxito y usted implementa el cambio con confianza.

1
En primer lugar, gracias por su respuesta: no esperaba ningún avance adicional en esta pregunta ... En segundo lugar, debo admitir que tiene razón sobre las operaciones simples: incluso un INSERT de dos columnas puede producir un error. Si está escrito para que el orden de las columnas pueda compararse con los argumentos, entonces puede estar bien, pero tiene razón, nuevamente: probablemente sea mejor mantener toda la aplicación bajo el régimen de prueba.
dezso

@dezso Es una gran pregunta y un concepto que necesita mucha más exposición en el mundo de la base de datos.
Leigh Riffel

"deberías probar toda la cadena de eventos como una unidad" - esto es lo más contraintuitivo que podrías decir. No es una unidad si ese es el caso. Estás haciendo pruebas de integración
Joe Phillips

@ Joe Philips: llámalo como quieras, asegurándote de que un procedimiento que inserte y dispare algunos disparadores haga lo que se supone que necesita tener pruebas automatizadas.
Leigh Riffel

8

Para PostgreSQL, consulte pgTAP :

pgTAP es un conjunto de funciones de base de datos que facilitan la escritura de pruebas unitarias de emisión de TAP en scripts psql o funciones de prueba de estilo xUnit.


Visto eso, gracias. ¿Alguien tiene experiencia con eso?
dezso

Sí, bastantes personas hoy en día. Suscríbase a la lista de correo si tiene preguntas.
teoría

6

Si prefiere que las pruebas de los procedimientos almacenados se realicen completamente en SQL, eche un vistazo a http://tsqlt.org/

Es compatible con MS SQL 2005 SP2 y superior, y la ventaja es que los desarrolladores no necesitan saber C # u otro lenguaje para implementar las pruebas.

También hay instalaciones para hacer simulaciones de tablas y vistas para ayudarlo a lograr un conjunto de pruebas ejecutable.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.