Caso de uso: tenemos una base de datos bastante grande (alrededor de 200 tablas) que se utiliza en un sistema grande (heredado). Se implementa como un enfoque de base de datos primero, con un archivo edmx que define la base de datos completa. Estamos utilizando XUnit y Effort para pruebas automáticas. El problema es que estas pruebas son muy lentas. Se necesita algo así como 7-8 minutos para ejecutar nuestro conjunto de pruebas actual, a pesar de que la cobertura de la prueba no está ni cerca de lo que queremos que sea.
Me di cuenta de que si creo un subconjunto más pequeño del archivo edmx , al eliminar algunas tablas que no son necesarias, las pruebas se ejecutan más rápido.
Estoy buscando una solución donde, para una prueba en particular, o un conjunto de pruebas, de alguna manera podamos hacer que Effort solo cree el subconjunto de tablas que se necesitan (creo que en muchos casos, solo necesitaremos una tabla).
Actualmente estamos configurando nuestra conexión de esta manera:
connection = EntityConnectionFactory.CreateTransient("metadata=res://entities.csdl|res://entities.ssdl|res://entities.msl");
¿Hay alguna forma de que podamos (por ejemplo, ejecutando una transformación XML en tiempo de ejecución), hacer que Effort solo cree las estructuras de datos que necesita para un subconjunto de tablas que definimos?
Descargo de responsabilidad : soy el propietario del proyecto Entity Framework Effort
Nuestra biblioteca tiene una característica que permite crear un punto de restauración y retroceder.
Entonces, al usar este truco, puede usar CreateRestorePoint()
solo una vez cuando se crean todas las tablas y luego para cada prueba, iniciarlas con RollbackToRestorePoint
. (Hay varias otras formas de hacerlo funcionar, pero supongo que entiendes el punto)
Sin duda hará que su prueba se ejecute MUCHO más rápido ya que la tabla no tendrá que crearse cada vez.
Aquí hay un ejemplo:
var conn = Effort.DbConnectionFactory.CreateTransient();
using (var context = new EntityContext(conn))
{
context.EntitySimples.Add(new EntitySimple { ColumnInt = 1 });
context.EntitySimples.Add(new EntitySimple { ColumnInt = 2 });
context.EntitySimples.Add(new EntitySimple { ColumnInt = 3 });
context.SaveChanges();
}
// Create a RestorePoint that will save all current entities in the "Database"
conn.CreateRestorePoint();
// Make any change
using (var context = new EntityContext(conn))
{
context.EntitySimples.RemoveRange(context.EntitySimples);
context.SaveChanges();
}
// Rollback to the restore point to make more tests
conn.RollbackToRestorePoint();
Separe la prueba de la unidad y la prueba de integración. Para la prueba de integración, puede usar la base de datos y ejecutarla en entornos superiores (para ahorrar tiempo), pero en entornos locales puede usar Faker \ Bogus y NBuilder para generar datos masivos para pruebas unitarias.
https://dzone.com/articles/using-faker-and-nbuilder-to-generate-massive-data
Otra opción es que puede crear el archivo de recursos correspondiente a los casos de prueba de su unidad https://www.danylkoweb.com/Blog/the-fastest-way-to-mock-a-database-for-unit-testing-B6
También me gustaría echarle un vistazo al rendimiento de InMemoryDB vs SqlLite, http://www.mukeshkumar.net/articles/efcore/unit-testing-with-inmemory-provider-and-sqlite-in-memory-database-in- ef-core
Aunque el ejemplo anterior es para EFCore, en EF6 también podemos usar SqlLite https://www.codeproject.com/Tips/1056400/Setting-up-SQLite-and-Entity-Framework-Code-First
Entonces, mi recomendación para usted es ir con sqllite para los escenarios de prueba de integración. Para la prueba de la unidad, puede utilizar sqllite o Faker \ Bogus y NBuilder.
¡Espero eso ayude!