c# database unit-testing

c# - Pruebas unitarias: configuración de la base de datos para las pruebas.



database unit-testing (7)

Aquí está el enfoque general que trato de usar. Concibo las pruebas en aproximadamente tres o cuatro niveles: pruebas unitarias, pruebas de interacción, pruebas de integración, pruebas de aceptación.

En el nivel de prueba de la unidad, es sólo el código. Cualquier interacción con la base de datos se simula, ya sea manualmente o utilizando uno de los marcos populares, por lo que la carga de datos no es un problema. Corren rápido y se aseguran de que los objetos funcionen como se espera. Esto permite ciclos de prueba de escritura / código de escritura muy rápidos. Los objetos simulados sirven los datos que necesita cada prueba.

Las pruebas de interacción prueban las interacciones de las interacciones de clase no triviales. Una vez más, no se requiere base de datos, se burla.

Ahora, en el nivel de integración, estoy probando la integración de componentes, y ahí es donde se lanzan las bases de datos reales, las colas, los servicios, yada yada. Si puedo, usaré una de las bases de datos populares en la memoria, así que inicialización no es un problema Siempre comienza vacío, y uso clases de utilidad para limpiar la base de datos y cargar exactamente los datos que quiero antes de cada prueba, para que no haya acoplamiento entre las pruebas.

El problema que encontré al usar bases de datos en memoria es que a menudo no son compatibles con todas las funciones que necesito. Por ejemplo, quizás requiera una combinación externa, y la base de datos en memoria no lo admite. En ese caso, normalmente probaré con una base de datos convencional local como MySQL, nuevamente, restregándolo antes de cada prueba. Dado que la aplicación se implementa en la producción en un entorno separado, los datos no se ven afectados por el ciclo de prueba.

Estoy escribiendo pruebas unitarias para una aplicación que utiliza una base de datos, y me gustaría poder ejecutar la aplicación contra algunos datos de muestra / prueba, pero no estoy seguro de cuál es la mejor manera de configurar los datos de prueba iniciales. para las pruebas.

Lo que busco es un medio para ejecutar el código bajo prueba en la misma base de datos (o esquemáticamente idéntica) que actualmente utilizo mientras depuro, y antes de cada prueba, me gustaría asegurarme de que la base de datos se reinicie. una pizarra limpia antes de insertar los datos de prueba.

Me doy cuenta de que usar un patrón IRepository me permitiría eliminar la complejidad de las pruebas con una base de datos real, pero no estoy seguro de que eso sea posible en mi caso.

¿Alguna sugerencia o artículo que pueda orientarme en la dirección correcta?

¡Gracias!

--EDITAR--

Gracias a todos, esas son algunas grandes sugerencias! Probablemente seguiré la ruta de burlarse de mi capa de acceso a datos, combinada con algunas clases de configuración simples para generar exactamente los datos que necesito por prueba.


Este código borra todos los datos de las tablas de todos los usuarios en MS SQL Server:

private DateTime _timeout; public void ClearDatabase(SqlConnection connection) { _timeout = DateTime.Now + TimeSpan.FromSeconds(30); do { SqlCommand command = connection.CreateCommand(); command.CommandText = "exec sp_MSforeachtable ''DELETE FROM ?''"; try { command.ExecuteNonQuery(); return; } catch (SqlException) { } } while (!TimeOut()); if (TimeOut()) Assert.Fail("Fail to clear DB"); } private bool TimeOut() { return DateTime.Now > _timeout; }


La burla es la causa de la mejor manera de probar su código de unidad.

En cuanto a las pruebas de integración, he tenido algunos problemas con el uso de bases de datos en memoria como SQLite, principalmente debido a pequeñas diferencias en el comportamiento y / o la sintaxis.

He estado usando una instancia local de MySql para pruebas de integración en varios proyectos. Un problema recurrente es la configuración del servidor y la creación de datos de prueba. He creado un pequeño paquete de Nuget llamado Mysql.Server (ver más en https://github.com/stumpdk/MySql.Server ), que simplemente configura una instancia local de MySql cada vez que ejecuta sus pruebas.

Con esta instancia en ejecución, puede configurar fácilmente estructuras de tablas y datos de muestra para sus pruebas sin preocuparse por su entorno de producción o la configuración del servidor local.


La mejor manera que he encontrado para manejar esto es usar una base de datos de prueba estática con datos conocidos, y usar transacciones para asegurar que sus pruebas no cambien nada.

En su configuración de prueba, iniciaría una transacción, y en su limpieza de prueba, desharía la transacción. Esto le permite modificar los datos en sus pruebas, pero también se asegura de que todo se restaure a su estado original cuando finalice la prueba.


Me pareció mejor hacer que mis pruebas fueran a una base de datos diferente para poder limpiarlas y colocar los datos que deseaba para la prueba.

Es posible que desee que la base de datos sea algo que se pueda configurar dentro del programa, luego su prueba puede indicar a las clases que cambien la base de datos.


No creo que haya una manera fácil de terminar esto. Solo tiene que crear los scripts de configuración SQL Pre-Test y los scripts Tear-down post-test. Entonces necesitas activar esos scripts para cada ejecución. Mucha gente sugiere SQLLite para la configuración de prueba unitaria.


Sé que estás usando C # pero en el mundo Java está el framework Spring. Le permite ejecutar minipulaciones de base de datos en una transacción y después de esta transacción, puede revertirla. Esto significa que usted opera en una base de datos real sin tocar el estado después de que finalice la prueba. Quizás esto podría ser un indicio de una mayor investigación en C #.