Problemas con el atributo DeploymentItem


94

Actualmente estoy manteniendo un sistema "antiguo" escrito en C # .net, eliminando algunas características obsoletas y haciendo una refactorización. Gracias a Dios, el chico anterior escribió algunas pruebas unitarias (MSTests). Me sentí bastante cómodo con las pruebas de JUnit, pero todavía no hice mucho con MSTests.

Los métodos de prueba tienen un DeploymentItematributo, que especifica un archivo de texto que se analiza mediante el método de lógica empresarial que se está probando y un segundo DeploymentItemen el que solo se ha especificado una ruta que contiene un montón de archivos TIF que también deben implementarse.

[TestMethod()]
[DeploymentItem(@"files\valid\valid_entries.txt")]
[DeploymentItem(@"files\tif\")]
public void ExistsTifTest()
{
   ...
}

Las pruebas funcionaron antes, pero ahora tuve que cambiar los nombres de los archivos TIF contenidos en el directorio \ files \ tif. Según una regla, los nombres de archivo TIF deben coincidir con un patrón determinado que también es verificado por el ExistsTifTest()método. Ahora tuve que cambiar los nombres de los archivos para adaptarlos a los nuevos requisitos y, de repente, los archivos TIF ya no se implementan como antes.

¿Alguien puede darme una pista de por qué sucede esto o cuál puede ser la causa? Lo mismo sucede también si agrego un nuevo archivo de texto, diga "my2ndTest.txt" al lado de "valid_entries.txt" en el directorio \ files \ valid \ con el atributo DeploymentItem correspondiente en el método de prueba. ¿El archivo no se implementa?

Obtuve las imágenes ahora implementadas definiendo la ruta de implementación directamente en testrunconfig, pero me gustaría entender por qué suceden estas cosas o por qué, por ejemplo, mi nuevo archivo "my2ndTest.txt" no se implementa mientras que los demás sí.


2
Un gran problema aquí es darse cuenta de que todos los elementos especificados en DeploymentItemAttribute se copiarán en la ubicación desde donde se ejecutan los ensamblados de prueba. En otras palabras, si esperaba que preservara la estructura de su directorio, no tendrá suerte. Si necesita copiarlo en un directorio específico, utilice la versión de dos parámetros DeploymentItem (source, outputDir). FYI: puede ir a la vieja escuela para averiguar dónde se ejecutan los archivos para MsTest colocando un System.Console.WriteLine (System.Environment.CurrentDirectory) en una de sus pruebas. ¡NCrunch no tuvo este problema!
CodeMonkeyKing

Respuestas:


111

DeploymentItem es un poco desordenado.

Cada archivo de su solución tendrá una configuración de "Copiar a carpeta de salida" en VS.NET. Necesita que sea "Copiar siempre" (o similar) para poder colocar los archivos en la carpeta de salida.

Compruebe que tiene este conjunto para los nuevos archivos. Si no tiene este conjunto, los archivos no se copiarán en la carpeta de salida, y luego no se podrán implementar desde la carpeta de salida a la carpeta donde MSTest lo hace.

Personalmente, si tengo archivos que necesito para mis pruebas unitarias, descubrí que incrustar esos archivos como recursos en un ensamblaje y hacer que ese ensamblaje se "descomprima" durante las pruebas es una forma más predecible de hacer las cosas. YMMV.

nota: Estos comentarios se basan en mi experiencia con VS2010. Los comentarios a mi respuesta sugerirían que esto no es un problema con VS2012. Todavía mantengo los comentarios de que el uso de recursos integrados implica menos "magia" y, para mí, hace que la etapa de "organizar" de mis pruebas unitarias sea mucho más explícita.


3
Copiar al directorio de salida nunca afecta la forma en que MSTest implementa los archivos. Esta respuesta es incorrecta.
KZU

19
En VS2010 Premium, realizar este cambio (y ningún otro cambio) provocó la implementación del archivo. Por lo tanto, concluyo basado en evidencia real de que SÍ afecta la implementación de MsTest.
JonStonecash

1
Convenido. He visto este cambio único poner el ceño fruncido de DeploymentItem.
Martin Peck

2
Parece que esto ya no es necesario en VS2012. Mis elementos de implementación se están implementando con "Copiar en carpeta de salida" configurado en "No copiar".
Mike

29
Es genial cómo DeploymentItem no le avisa cuando no puede copiar el único archivo que le ha proporcionado.

74

En VS2010, mi Local.testsettings tenía la opción "Habilitar implementación" desmarcada y el atributo DeploymentItem no funcionaba. Lo revisé y todo funcionó bien. ¡Espero que esto ayude!


2
Me he estado golpeando la cabeza contra una pared de ladrillos durante años tratando de que funcione ... ¡gracias!
mat-mcloughlin

12
Creo que hubiera sido bueno si el marco emitiera una advertencia de que los atributos de DeploymentItem se ignoran si esta configuración está desactivada. También puse una bonita impresión cóncava en mi escritorio.
Alan McBee - MSFT

2
Tenga en cuenta que Local.testsettings está en Elementos de solución
Matthew Lock

También tuve que agregar el directorio que contiene los elementos que quería implementar en Local.testsettings también: i.imgur.com/p1z3m9R.png
Matthew Lock

El uso de VS2017 en 2018, marcando 'Habilitar implementación' sigue siendo la solución para este problema. Y, lamentablemente, todavía ahora advierte de Visual Studio en absoluto. Así que gracias por esta solución.
Don H

19

También me he enfrentado a problemas similares, pero encontré una solución fácil de 3 pasos para esto:

Suponiendo que la estructura de su carpeta se vea así: SolutionFolder\ TestProjectFolder\ SubFolder\

  1. Vaya a "Elementos de soluciones / Local.testsettings"> "Implementación"> Marque "Habilitar implementación"
  2. Si está utilizando VS2010, asegúrese de que los archivos que desee implementar tengan la propiedad "Copiar a la carpeta de salida" configurada en "Copiar siempre" o "Copiar si es más reciente".
  3. Atribuya su TestMethod con uno de los siguientes:
    • [DeploymentItem(@"TestProjectFolder\SubFolder")]para implementar todo el contenido de <SubFolder>en el directorio Test Run
    • [DeploymentItem(@"TestProjectFolder\SubFolder", "TargetFolder")] para implementar todo el contenido de <SubFolder>to <TargetFolder>en el directorio Test Run

Una nota final sobre MSTest (al menos para VS2010):

Si desea <TargetFolder>que tenga el mismo nombre que el <SubFolder>, el uso [DeploymentItem(@"SubFolder", @"SubFolder")]fallará silenciosamente ya que el corredor de MSTest golpea un caso de borde tonto. Esta es la razón por la que debe anteponer <SubFolder>el <TestProjectFolder>como tal:[DeploymentItem(@"TestProjectFolder\SubFolder", @"SubFolder")]


La nota sobre el error de denominación de subcarpetas es una joya.
RJ Lohan

1
VS 2015 parece ser un poco diferente. Necesitaba eliminar la parte "TestPojectFolder" en el atributo DeploymentItem.
uli78

15

Con suerte, para ayudar a alguien más: probé todas las sugerencias aquí y aún no se estaba copiando mi elemento de implementación.

Lo que tuve que hacer ( como se sugiere aquí ) fue agregar un segundo parámetro al atributo DeploymentItem:

[DeploymentItem(@"UnitTestData\TestData.xml", "UnitTestData")]

10

Si ingresa a su archivo .testrunconfig y en implementación desmarca "Habilitar implementación", las pruebas se ejecutarán en su ubicación normal y todo funcionará como lo hace cuando se ejecuta la aplicación fuera de una prueba unitaria.


También tuve algunos problemas con esto. Como PM, no tengo acceso a todas las herramientas utilizadas por dev. En este caso, ReSharper copió el archivo correctamente mientras que MSTest no lo hizo. -> Experimenté errores mientras el desarrollador estaba bien. Cambie a 'Prueba-> Editar configuración de prueba -> Configuración local -> Implementación', incluido el archivo en cuestión, lo solucionó para mi uso de MSTest.
sonstabo

9

Esto probablemente no se relaciona con su problema exacto, pero aquí hay un par de consejos que encontré con el atributo [DeploymentItem].

  1. Copiar al directorio de salida debe establecerse en Copiar siempre.

No NO funciona cuando se utiliza con el atributo [TestInitialize]

[TestInitialize]
[DeploymentItem("test.xlsx")]
public void Setup()
{

Debe estar en su [TestMethod], p. Ej.

    [TestInitialize]
    public void Setup()
    {
        string spreadsheet = Path.GetFullPath("test.xlsx");
        Assert.IsTrue(File.Exists(spreadsheet));
        ...
    }

    [TestMethod]
    [DeploymentItem("test.xlsx")]
    public void ExcelQuestionParser_Reads_XmlElements()
    {
        ...
    }

1
Esta es una limitación increíblemente molesta. Siento que en muchos casos, el momento de la implementación debería ser Inicializar. ¿Qué pasa si todas mis pruebas usan los mismos artefactos de soporte? Supongo que se supone que debo copiar y pegar decoradores en docenas de métodos de prueba. Ridículo.
Ryanman

5

Después de probar todas las otras sugerencias enumeradas aquí, todavía no podía entender qué estaba pasando. Finalmente descubrí que no había ningún archivo de configuración seleccionado en el menú Prueba / Configuración de prueba, lo que significaba que la implementación no estaba habilitada. Hice clic en el elemento del menú Prueba / Configuración de prueba / Seleccionar archivo de configuración de prueba, seleccioné el archivo Local.TestSettings, luego todo funcionó.


4

No estoy seguro de si esto responde exactamente a la pregunta, pero puede ayudar a algunos. Primero, descubrí que la casilla "Habilitar implementación" debe estar marcada para que la implementación funcione. En segundo lugar, el documento dice que la ruta de origen es "relativa a la ruta del proyecto", que al principio tomé como la carpeta del proyecto. De hecho, parece referirse a la carpeta de salida de la compilación. Entonces, si tengo una carpeta de proyecto llamada 'TestFiles' y un archivo llamado Testdata.xml, usar el atributo de esta manera no funciona:

[DeploymentItem(@"TestFiles\Testdata.xml")] 

Puedo marcar el Testdata.xmlarchivo Copy Always, para que la compilación coloque una copia en la carpeta de salida (por ejemplo, Debug\TestFiles\TestData.xml). El mecanismo de implementación encontrará la copia del archivo ubicado en esa ruta ( TestFiles\Testdata.xml) en relación con la salida de la compilación. O puedo establecer el atributo de esta manera:

[DeploymentItem(@"..\\..\TestFiles\Testdata.xml")] 

y el mecanismo de implementación encontrará el archivo original. Entonces, cualquiera de las dos funciona, pero he notado que al usar el Copy Always, ocasionalmente me encuentro con el mismo problema que tengo al editar el archivo app.config en un proyecto: si no cambio el código ni fuerzo una reconstrucción, nada activa la copia de archivos marcados como ser copiado en compilación.


La ruta relativa fue el problema para mí y esto lo solucionó. Agregué 2 conjuntos de declaraciones DeploymentItem dependiendo de cómo se ejecutaron las pruebas.
Ed Bayiates

3

Primero tenía la bandera de implementación deshabilitada. Pero incluso después de que lo habilité, por alguna razón desconocida, no se copiaría nada, ni siquiera las DLL de destino. Accidentalmente abrí la ventana Test Run y ​​eliminé todas las ejecuciones anteriores y mágicamente encontré todas las DLL y archivos que necesitaba en la carpeta de prueba la siguiente ejecución ... Muy confuso.


2

Estaba teniendo grandes problemas al intentar que los archivos se implementaran, probando todas las sugerencias anteriores.

Luego cerré VS2010; lo reinició, cargó la solución y todo funcionó. (!)

Hice algunas comprobaciones; Después de configurar el indicador 'Habilitar implementación' en local.TestSetting, no debe simplemente volver a ejecutar la prueba desde la ventana Resultados de la prueba. Debe eliminar la ejecución de prueba anterior de la interfaz de usuario, por ejemplo, ejecutando una prueba diferente o volviendo a abrir su solución.


2

No lo use DeploymentItem.

Es muy difícil configurarlo correctamente y no funcionaba con mi ejecutor de pruebas ReSharper ni con el nativo de MSTEST en Visual Studio 2017.

En su lugar, haga clic derecho en su archivo de datos y seleccione propiedades . Seleccione Copiar al directorio de salida: Siempre .

Ahora en tu prueba, haz esto. El directorio es simplemente el directorio del archivo relativo al proyecto de prueba. Fácil.

    [TestMethod()]
    public void ParseProductsTest()
    {
        // Arrange
        var file = @"Features\Products\Files\Workbook_2017.xlsx";
        var fileStream = File.Open(file, FileMode.Open);
        // etc.
    }

Esto parece funcionar bien con sistemas de prueba y compilación automatizados.


1

Como siempre encontré el atributo DeploymentItem un desastre, hago la implementación de dichos archivos utilizando el script posterior a la compilación. - Asegúrese de que los archivos que desea copiar tengan configurada la propiedad Copiar siempre. - Modifique el script posterior a la compilación del proyecto de prueba para copiar los archivos de la carpeta de destino de la compilación (Bin \ Debug) a la ubicación donde los espera la prueba.


1

Pruebe esto para VS2010. Por lo tanto, no es necesario agregar DeployItems para cada tif
Elimine el

[DeploymentItem(@"files\valid\valid_entries.txt")]  
[DeploymentItem(@"files\tif\")]  

Agregue una configuración de prueba.
- haga clic con el botón derecho en el nodo de la solución en el explorador de soluciones
- Agregar -> Nuevo elemento ...
- Seleccione el nodo Configuración de prueba a la izquierda, seleccione el elemento a la derecha
- Haga clic en Agregar

Llámalo eg TDD

Elija TDDen TestMenu> Edit Testsettings.

Haga clic en Implementación. Habilítelo y luego agregue los archivos y directorios que desee. Habrá una ruta relativa a la solución. Los archivos se guardarán. El archivo original está, por ejemplo, aquí:

D:\Users\Patrik\Documents\Visual Studio 2010\Projects\DCArrDate\WebMVCDCArrDate\Trunk\WebMVCDCArrDate\Authority.xml  

Cuando ejecuto mi prueba unitaria, se copia a

D:\Users\Patrik\Documents\Visual Studio 2010\Projects\DCArrDate\WebMVCDCArrDate\Trunk\WebMVCDCArrDate.Tests\bin\Debug\TestResults\Patrik_HERKULES 2011-12-17 18_03_27\Authority.xml  

en testcode lo llamo desde:

[TestMethod()]
public void Read_AuthorityFiles_And_ParseXML_To_Make_Dictonary()  
{  
  string authorityFile = "Authority.xml";  
  var Xmldoc = XDocument.Load(authorityFile);  

No es necesario elegir Copiar siempre; poner los archivos en el proyecto de prueba; agregue rutas codificadas en el código de prueba. Para mí, esta solución funcionó mejor. Probé con DeploymentItem, copiar siempre pero no fue de mi agrado.


1

Para aquellos que prefieren evitar el desorden de DeploymentItem y adoptar el enfoque sugerido por @Martin Peck (respuesta aceptada), pueden usar el siguiente código para acceder al contenido del recurso incrustado:

public string GetEmbeddedResource(string fullyQulifiedResourceName)
{
    var assembly = Assembly.GetExecutingAssembly();
    // NOTE resourceName is of the format "Namespace.Class.File.extension";

    using (Stream stream = assembly.GetManifestResourceStream(fullyQulifiedResourceName))
    using (StreamReader reader = new StreamReader(stream))
    {
        string result = reader.ReadToEnd();
    }
}

Para obtener más información, consulte este hilo SO


1
He tenido problemas con Assembly.GetExecutingAssembly () cuando se ejecuta en un servidor de compilación -> devolvería el corredor de prueba en lugar del ensamblaje de prueba real. Obtener el ensamblaje reflejándolo de un tipo fijo en el ensamblaje de prueba (por ejemplo, su clase de prueba) resolvió esto por mí.
Arno Peters

1

Para mí, la causa raíz era algo completamente diferente: el código de producción que ejercían mis pruebas cambiaba el nombre y / o eliminaba el archivo de prueba .xml que se estaba implementando.

Por lo tanto, cuando ejecutaba mis pruebas individualmente, pasaban, pero cuando las ejecutaba todas juntas, la segunda prueba y las posteriores fallaban con errores de "archivo no encontrado" (que originalmente diagnostiqué erróneamente como el DeploymentItematributo que no funciona).

Mi solución fue que cada método de prueba individual hiciera una copia del archivo implementado (usando esta técnica ), y luego que el código de producción que se estaba probando usara el archivo copiado en lugar del original.


1

Hemos dedicado mucho tiempo al problema de los elementos de implementación para resolverlo en la ejecución de prueba de unidad local y también en la reunión de prueba de unidad de teamcity. No es facil.

Una muy buena herramienta para depurar este problema es ProcessExplorer . Con el explorador de procesos, puede verificar dónde está Visual Studio buscando los elementos de implementación y realizar la corrección en el proyecto. Simplemente filtre todas las operaciones de archivo donde la ruta contenga el nombre de archivo de su elemento de implementación y lo verá.


Sé que esta es una respuesta muy antigua, pero si puede explicar cómo usa ProcessExplorer, sería útil. No veo cómo ver las operaciones de archivos en absoluto, y mucho menos filtrarlas ...
David

1

Además del atributo Deployment que debe comprobarse, descubrí algo más sobre el atributo DeploymentItem.

[TestMethod()]
[DeploymentItem("folder\subfolder\deploymentFile.txt")]
public void TestMethod1()
{
   ...
}

Su deploymentFile.txt debe ser relativo al archivo de la solución y no al testfile.cs.

ingrese la descripción de la imagen aquí


Finalmente conseguí que esto funcionara haciendo que mi fuente DeploymentItem fuera relativa al proyecto de prueba. Entonces tengo un proyecto en mi solución, "Service.Tests". Debajo tengo una carpeta "FilesForTests" que tiene los archivos que quiero copiar. Yo usé [DeploymentItem(@"FilesForTests\MyFile.txt", "FilesForTests")]. Yo creo que estamos diciendo lo mismo?
David

1

He estado trabajando en esto en VS2013. Mis hallazgos para que esto funcione:

  • Copiar al directorio de salida debe establecerse en Copiar si es más reciente / Copiar siempre: OBLIGATORIO.
  • "Habilitar la implementación" en .TestSettings: NO ES NECESARIO. Conseguí que esto funcionara sin un archivo .TestSettings en absoluto.
  • Especificar una carpeta como segundo parámetro: OPCIONAL. Da forma al diseño de la carpeta de salida, funciona bien sin.
  • ESPACIOS en el nombre del archivo: esto me causó un dolor de cabeza, el archivo nunca se copió. Eliminar los espacios solucionó esto. Aún no he investigado los personajes de escape.

Un consejo que también aprendí por las malas: no olvides agregar este atributo a cada prueba individual. El archivo se copia en la primera prueba atribuida en el testrun, pero seguía faltando cuando el orden de las pruebas cambió y las pruebas no atribuidas intentaron encontrar el archivo primero.


Probé todo aquí antes de llegar a su respuesta, que fue la última. El culpable: ¡ESPACIOS EN EL NOMBRE DE ARCHIVO! Buen rótulo.
joelmdev

1
Usando Visual Studio 2019. "Copiar si es más nuevo" lo solucionó. Odio "Copiar siempre" porque obliga al proyecto a reconstruirse en muchos escenarios como depuración o compilación incremental.
Gerardo Grignoli

Convenido. He actualizado mi respuesta para incluir Copiar si es más reciente.
Arno Peters

0

Mi gran problema fue la forma en que DeploymentItem maneja los directorios. Estaba usando la versión de dos parámetros con ambos como ruta de directorio que contiene los subdirectorios que quería implementar. ¡No me di cuenta inicialmente de que solo copia las cosas en la RAÍZ del directorio y no toda la estructura de carpetas recursivas!

Básicamente tenía [DeploymentItem (@ "Foo \", @ "Foo \")] y esperaba que implementara mi Foo \ Bar. Específicamente tuve que cambiarlo a [DeploymentItem (@ "Foo \ Bar \", @ "Foo \ Bar \")] y ahora funciona como un encanto.


0

También me he enfrentado a problemas similares. Tengo todos los pasos mencionados anteriormente, pero aún así no tuve suerte. Estoy usando VS2010. Luego descubrí que se seleccionó $ Menu> Test> Select Active Test Setting> Trace and Test impact . Comenzó a funcionar después de cambiar Trace y probar el impacto a Local . Esta página contiene información muy útil sobre cómo copiar archivos a la carpeta de resultados de la prueba, creo que también debo agregar esta experiencia.

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.