2010-03-18 11 views
9

He buscado en Google esto un poco y realmente no encontré la respuesta que necesitaba.Unidad prueba insertar/actualizar/eliminar

Estoy trabajando en una página web en C# con SQL Server y LINQ para un cliente. Quiero que los usuarios puedan enviarse mensajes entre ellos. Entonces, lo que hago es probarlo con datos que realmente entran en la base de datos.

El problema es que ahora dependo de tener al menos 2 usuarios de quienes conozco la ID de. Además, tengo que limpiarme después de mí mismo. Esto conduce a pruebas unitarias bastante grandes que prueban mucho en una prueba.

Digamos que me gustaría actualizar un usuario. Eso significaría que tendría que citar al usuario, actualizarlo y luego eliminarlo. Esto es una gran cantidad de aserciones en una prueba de unidad y si falla con la actualización tengo que eliminarlo manualmente.

Si lo haría de ninguna otra manera, sin guardar los datos de DB, no estaría seguro será capaz de saber que los datos estuvo presente en la base de datos después de la actualización, etc

¿Cuál es la forma correcta hacer esto sin tener una prueba que prueba mucha funcionalidad en una prueba?

+3

"Así que lo que hago es que pruebo esta unidad con datos en vivo" Eso es contradictorio. Los datos en vivo significan que no están realizando pruebas unitarias, están realizando pruebas de usabilidad o pruebas de rendimiento o quizás pruebas de integración. Pruebas unitarias significa "prueba muchas funcionalidades por sí mismo". Tal vez deberías actualizar la pregunta. –

+0

Gracias por señalar eso, algo salió mal en mi cabeza. Edité ahora –

Respuesta

17

hacer todas las pruebas dentro de un bloque System.Transactions.TransactionScope, y simplemente no llaman Scope.Complete() ... Todos los cambios se retrotraerán cuando salga, y otros usuarios no podrán ver los datos temporales que usted crea en la base de datos, por lo que el proceso de prueba solo afectará a la máquina de prueba ..

Usted puede ingresar un nuevo usuario, leer la base de datos para verificar que se haya ingresado correctamente y cualquier otra cosa que necesite verificar, dentro del bloque de TransactionScope ...

Haga que el método de prueba de una sola unidad suplante a los dos usuarios diferentes, todo dentro de la transacción ...

p. código

using (var scop = new System.Transactions.TransactionScope()) 
    { 
     // all your test code and Asserts that access the database, 
     // writes and reads, from any class, ... 
     // to commit at the very end of this block, 
     // you would call 
     // scop.Complete(); // ..... but don't and all will be rolled back 
    } 
+0

Suena como lo que necesito. ¿Funcionaría esto como si los datos estuvieran en la base de datos, pero no me comprometería? Estoy accediendo a los datos en algunas clases y ellos tendrán que "pensar" que los datos están en el DB –

+0

. Otros usuarios * podrían * verlo si juegan con el nivel de aislamiento de transacción. Sin embargo, suele ser una acción deliberada, así que no es realmente algo de lo que preocuparse. – DaveE

+0

¿Cómo funciona esto? ¿Están los datos almacenados en la base de datos mientras tanto o están almacenados en la memoria? –

4

Tiene un archivo de dispositivos (en XML, SQL, YAML, lo que sea) que puede cargar en la base de datos de prueba local con solo un comando.

E.g. un archivo de accesorios para dos usuarios que necesitan mensaje entre sí pueda parecer (esto es mío):

Member: 

    Member_WibWobble: 
    username:  Wibble_Wobble 
    email_address: [email protected][removed].com 
    password:  pw 
    is_super_admin: true 
    last_login:  "2010-01-06 12:12:57" 
    Country:  country_AU 
    UploadImage: 
     type:   <?php echo UploadImage::TYPE_MEMBER_AVATAR."\n"; ?> 
     upload:  "http://localhost/[removed]/images/wibwobble.jpg" 

    Member_BunnyHugs: 
    username:  BunnyHugs 
    email_address: [email protected][removed].com 
    password:  pw 
    is_super_admin: true 
    last_login:  "2009-12-01 14:11:11" 
    Country:  country_UK 
    UploadImage: 
     type:   <?php echo UploadImage::TYPE_MEMBER_AVATAR."\n"; ?> 
     upload:  "http://localhost/[removed]/images/bunnyhugs.jpg" 

PrivateMessage: 

    PrivateMessage_1: 
    subject:   "Yo" 
    body:   | 
     hi 

     <b>escape this html please</b> 

     bye 
    is_read:   false 
    Sender:   Member_WibWobble 
    Recipient:  Member_BunnyHugs 
+0

. Es una buena idea, especialmente si usa SQLite en otra base de datos basada en memoria. Eso le proporcionará un rendimiento mucho mejor, especialmente si desea probar con grandes conjuntos de datos. –

+0

¿Pero esto no significa que tendría que agregar estos datos al DB para probarlo ...? –

+0

@Kurresmack: Sí. – NotMe

4

Las bases de datos de pruebas unitarias pueden ser un PITA debido a su propia naturaleza (almacenamiento persistente).

Para hacer esto bien, siempre debe comenzar con un esquema en blanco. Luego haga que su carga de código de prueba complete los valores de datos que deben estar allí. Esto puede ser tan simple como simplemente ejecutar un script sql que contenga el esquema y los datos predeterminados.

Una vez hecho esto, comience a ejecutar sus pruebas. Las pruebas deben abarcar todas las operaciones crud que su aplicación normalmente hará.

Si ocurre alguna falla, no es una gran oferta porque, una vez más, debe comenzar de nuevo cada vez.

Además, desea mantener esos datos en caso de una falla de prueba para que pueda inspeccionar el estado de la base de datos en el momento en que ocurrió la falla. Entonces, esto es algo bueno y malo.

En este sentido, las pruebas de db se deben ejecutar en su propia instancia de base de datos de prueba. De esta manera, no tiene que preocuparse por problemas transitorios, como que alguien cambie una estructura de DB debajo de usted a medida que avanzan las pruebas.

En última instancia, las pruebas de bases de datos son un proyecto en sí mismo.