2010-07-20 15 views
12

Tengo algunas funciones que dicen & modificar archivos. Para hacer las pruebas unitarias independientemente de cualquier problema del sistema de archivos, quiero incluir los archivos dentro del proyecto.Incluye el archivo de recursos para la prueba unitaria en el proyecto C#

Sin embargo, mi función debería ser obtener filePath, y todo lo que puedo obtener del ensamblado es un FileStream. ¿Alguna idea de cómo puedo obtener la ruta del archivo de un archivo de recursos en el proyecto?

System.Reflection.Assembly a = System.Reflection.Assembly.Load(assemblyName); 
FileStream stream = a.GetFile(assemblyName + "." + fileName); 

Gracias!

+1

mi humilde opinión este tipo de ensayo de datos nunca debe ser incorporado en la prueba y debe ser suministrado por separado (que también le permite volver a ejecutar la prueba con diferentes datos sin reconstrucción). ¿Qué tipo de problemas con el sistema de archivos le preocupa? –

+2

No me gusta que las pruebas de la unidad dependan de recursos externos, que se pueden modificar, mover, cambiar, etc. Esta prueba unitaria se realiza para verificar 1 escenario, y quiero que se pruebe ese escenario exacto, por lo que debe ser independiente del hecho de que los permisos de archivo se puedan cambiar, demasiados manejadores de archivos abiertos, disco NTFS no disponible, etc. – Yossale

+0

Creo que esta es una muy buena pregunta. En cuanto a las pruebas de unidades reales, reconozco que se debe evitar el uso de datos de archivo, pero si piensas en pruebas de integración (por ejemplo, estoy escribiendo un lector de archivos), usar datos de prueba "reales" tiene sentido. – anhoppe

Respuesta

8

Mi solución habitual para este problema es que refactorizo ​​mi programa para abrir el archivo en el método de llamada y luego paso un Stream en lugar de pasar el nombre del archivo y abrir el archivo allí.

Para probar esto, me permite pasar un MemoryStream para que pueda escribir mi prueba de unidad sin usar el sistema de archivos. A veces es incluso más fácil comprobar si los datos se han escrito correctamente y es definitivamente más rápido, especialmente para un mayor número de pruebas. Solo tiene que recordar limpiar el MemoryStream después de escribir, ya que .NET no siempre lo hace automáticamente.

Ejemplo de uno de mis programas:

public TestSaveAndLoad() 
{ 
    [... create data to save ...] 
    using (MemoryStream targetStream = new MemoryStream()) 
    { 
    target.Save(targetStream); 
    targetStream.Flush(); 
    targetStream.Seek(0, ...); 
    target.Load(targetStream); 
    } 
    [... assert that the loaded data equals the saved data ...] 
} 
+0

Cool. No me gustaron todas esas secuencias, y parece una buena solución. – Yossale

0

Si configura la acción de compilación del archivo para copiar, puede predecir dónde debería estar el archivo (probablemente un montón de .. \ .. \ .. \ 's pero todavía). Supongo que tiene una entrada en su método para el nombre del archivo, por lo que debería funcionar bien.

Al igual que una sugerencia, ¿es posible abstraer la lectura/cambio real de ese archivo en un método y pasar un valor de cadena? La única razón por la que menciono esto es que huele como una prueba de integración (tocando el sistema de archivos).

4

Un recurso incrustado no existe en el sistema de archivos, por lo que no tiene ninguna ruta de archivo.

tiene dos opciones:

  • Cambiar la API de su SUT para que acepte una corriente en lugar de solamente una ruta de archivo. Esta solución es muy preferida.
  • Guarde el recurso incrustado en un archivo temporal durante la prueba unitaria, asegurándose de eliminarlo nuevamente después de cada caso de prueba.

La primera solución es un excelente ejemplo de cómo TDD nos impulsa hacia mejores APIs, más flexibles.

+0

Empecé con Stream s por todas partes, pero me sentí como si estuviera haciendo malabarismos con muchos controladores abiertos en el aire. Aunque lo pensaría un segundo. Gracias. – Yossale

+1

Siempre puede crear métodos sobrecargados: uno que toma una ruta de archivo, pero realmente solo delega al otro que toma un Stream ... –

1

Puede establecer los archivos de datos que se copiarán en el directorio bin cuando se construya el proyecto, y luego hacer referencia a ellos a través del Directory.GetCurrentDirectory() en su prueba. O incluso déjelos donde están y simplemente use una ruta relativa basada en el directorio actual.

Mejor, sin embargo, reestructurar su código para usar la clase Stream, luego usar una combinación de inyección de burla e inyección de dependencia para suministrar una corriente simulada con los datos, o usar una secuencia de memoria, si la falsificación funciona mejor.

+1

Algunos corredores de prueba no tienen el directorio bin como el directorio actual al ejecutar la prueba. Utilice 'AppDomain.CurrentDomain.BaseDirectory' para obtener el directorio de despliegue, no' Directory.GetCurrentDirectory() '. – Sjoerd

Cuestiones relacionadas