Problemi con l'attributo DeploymentItem


94

Attualmente sto mantenendo un "vecchio" sistema scritto in C # .net, rimuovendo alcune funzionalità obsolete e facendo un po 'di refactoring. Grazie a Dio, il ragazzo precedente ha scritto alcuni unit test (MSTest). Sono abbastanza a mio agio con i test JUnit, ma non ho fatto ancora molto con i test MST.

I metodi di test hanno un DeploymentItemattributo, che specifica un file di testo che viene analizzato dal metodo di logica aziendale che viene testato e un secondo in DeploymentItemcui è stato specificato solo un percorso contenente un gruppo di file TIF che devono essere distribuiti.

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

I test prima funzionavano, ma ora dovevo cambiare i nomi dei file TIF contenuti nella directory \ files \ tif. Secondo una regola, i nomi dei file TIF devono corrispondere a un certo modello che è anche controllato dal ExistsTifTest()metodo. Ora ho dovuto cambiare i nomi dei file per adattarli ai nuovi requisiti e improvvisamente i file TIF non vengono più distribuiti come prima.

Qualcuno può darmi un suggerimento perché questo accade o quale potrebbe essere la causa? La stessa cosa accade anche se aggiungo un nuovo file di testo dicendo "my2ndTest.txt" accanto a "valid_entries.txt" nella directory \ files \ valid \ con il corrispondente attributo DeploymentItem sul metodo di test. Il file non viene distribuito?

Ora ho distribuito le immagini definendo il percorso di distribuzione direttamente in testrunconfig, ma mi piacerebbe capire perché accadono queste cose o perché, ad esempio, il mio nuovo file "my2ndTest.txt" non viene distribuito mentre gli altri lo fanno.


2
Un grande trucco qui è rendersi conto che tutti gli elementi specificati in DeploymentItemAttribute verranno copiati nella posizione da cui vengono eseguiti gli assembly di test. In altre parole, se speravi che preservasse la struttura della tua directory, sarai sfortunato. Se è necessario copiarlo in una directory specifica, utilizzare la versione a due parametri DeploymentItem (source, outputDir). Cordiali saluti: puoi andare alla vecchia scuola per scoprire dove vengono eseguiti i file per MsTest inserendo System.Console.WriteLine (System.Environment.CurrentDirectory) in uno dei tuoi test. NCrunch non ha avuto questo problema!
CodeMonkeyKing

Risposte:


111

DeploymentItem è un po 'un casino.

Ogni file nella soluzione avrà un'impostazione "Copia nella cartella di output" in VS.NET. È necessario che sia "Copia sempre" (o simile) per caricare i file nella cartella di output.

Verifica di avere questo set per i nuovi file. Se non si dispone di questo set, i file non verranno copiati nella cartella di output e quindi non possono essere distribuiti dalla cartella di output alla cartella in cui MSTest fa le cose.

Personalmente, se ho file di cui ho bisogno per i miei test unitari, ho scoperto che incorporare quei file come risorse in un assembly e fare in modo che l'assembly si "decomprima" durante i test è un modo più prevedibile di fare le cose. YMMV.

nota: questi commenti si basano sulla mia esperienza con VS2010. I commenti alla mia risposta suggeriscono che questo non è un problema con VS2012. Continuo a sostenere i commenti che l'uso di risorse incorporate implica meno "magia" e, per me, rende la fase di "organizzazione" dei miei test unitari molto più esplicita.


3
Copia nella directory di output non influisce mai sul modo in cui MSTest distribuisce i file. Questa risposta non è corretta.
kzu

19
Su VS2010 Premium, questa modifica (e nessun'altra modifica) ha causato la distribuzione del file. Quindi, concludo sulla base di prove effettive che INFLUISCE sulla distribuzione di MsTest.
JonStonecash

1
Concordato. Ho visto questo singolo cambiamento capovolgere DeploymentItem accigliato.
Martin Peck

2
Questo sembra non essere più richiesto su VS2012. I miei elementi di distribuzione vengono distribuiti con "Copia nella cartella di output" impostato su "Non copiare".
Mike

29
È fantastico come DeploymentItem non ti dia alcun avviso quando non è in grado di copiare il singolo file che hai fornito.

74

In VS2010, il mio Local.testsettings aveva "Abilita distribuzione" deselezionato e l'attributo DeploymentItem non funzionava. L'ho controllato e tutto ha funzionato bene. Spero che aiuti!


2
Ho sbattuto la testa contro un muro di mattoni per anni cercando di farlo funzionare .... grazie!
mat-mcloughlin

12
Penso che sarebbe stato bello se il framework avesse emesso un avviso che gli attributi DeploymentItem vengono ignorati se questa impostazione è disattivata. Ho anche messo una bella impressione concava nella mia scrivania.
Alan McBee - MSFT

2
Nota che Local.testsettings è in Solution Items
Matthew Lock

Ho anche dovuto aggiungere la directory contenente gli elementi che volevo distribuire in Local.testsettings anche: i.imgur.com/p1z3m9R.png
Matthew Lock

L'utilizzo di VS2017 nel 2018 selezionando "Abilita distribuzione" è ancora la soluzione a questo problema. E purtroppo ancora ora un avviso da Visual Studio. Quindi grazie per questa soluzione.
Don H

19

Ho anche affrontato problemi simili ma ho trovato una facile soluzione in 3 passaggi per questo:

Supponendo che la struttura delle cartelle sia simile a questa: SolutionFolder\ TestProjectFolder\ SubFolder\

  1. Vai a "Solutions Items / Local.testsettings"> "Deployment"> seleziona "Enable Deployment"
  2. Se utilizzi VS2010, assicurati che tutti i file che desideri distribuire abbiano la proprietà "Copia nella cartella di output" impostata su "Copia sempre" o "Copia se più recente"
  3. Attribuisci il tuo TestMethod con uno dei seguenti:
    • [DeploymentItem(@"TestProjectFolder\SubFolder")]per distribuire tutto il contenuto di <SubFolder>nella directory Test Run
    • [DeploymentItem(@"TestProjectFolder\SubFolder", "TargetFolder")] per distribuire tutti i contenuti di <SubFolder>in <TargetFolder>nella directory Test Run

Un'ultima nota su MSTest (almeno per VS2010):

Se vuoi <TargetFolder>che abbia lo stesso nome di, l' <SubFolder>uso [DeploymentItem(@"SubFolder", @"SubFolder")]fallirà silenziosamente poiché il corridore MSTest colpisce uno stupido caso limite. Questo è il motivo per cui si dovrebbe anteporre la <SubFolder>con il <TestProjectFolder>come così:[DeploymentItem(@"TestProjectFolder\SubFolder", @"SubFolder")]


La nota sull'errore di denominazione delle sottocartelle è un gioiello.
RJ Lohan

1
VS 2015 sembra essere un po 'diverso. Avevo bisogno di rimuovere la parte "TestPojectFolder" nell'attributo DeploymentItem.
uli78

15

Spero di aver aiutato qualcun altro: ho provato tutti i suggerimenti qui e ancora il mio elemento di distribuzione non veniva copiato.

Quello che dovevo fare ( come suggerito qui ) era aggiungere un secondo parametro all'attributo DeploymentItem:

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

10

Se accedi al tuo file .testrunconfig e in distribuzione deseleziona "Abilita distribuzione", i test verranno eseguiti nella loro posizione normale e tutto funzionerà come quando si esegue l'app al di fuori di uno unit test.


Ho avuto anche dei problemi con questo. In qualità di PM non ho accesso a tutti gli strumenti utilizzati da dev. In questo caso ReSharper ha copiato il file correttamente mentre MSTest non è riuscito a farlo. -> Ho riscontrato errori mentre dev era OK. Passare a "Test-> Modifica impostazioni di prova -> Impostazioni locali -> Distribuzione" incluso il file in questione ha risolto il problema per il mio utilizzo MSTest.
sonstabo

9

Questo probabilmente non si riferisce al tuo problema esatto, ma ecco un paio di suggerimenti che ho trovato con l'attributo [DeploymentItem].

  1. La copia nella directory di output dovrebbe essere impostata su Copia sempre.

Esso non funziona quando viene utilizzato con l'attributo [TestInitialize]

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

Dovrebbe essere sul tuo [TestMethod], ad es

    [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
Questa è una limitazione follemente fastidiosa. Penso che in molti casi il tempo per la distribuzione dovrebbe essere in Initialize. Cosa succede se tutti i miei test utilizzano gli stessi artefatti di supporto? Immagino che dovrei copiare e incollare i decoratori su dozzine di metodi di prova? Ridicolo.
Ryanman

5

Dopo aver provato tutti gli altri suggerimenti elencati qui, non riuscivo ancora a capire cosa stesse succedendo. Alla fine ho scoperto che non era selezionato alcun file di impostazioni nel menu Impostazioni di test / test, il che significava che la distribuzione non era abilitata. Ho fatto clic sulla voce di menu Test / Impostazioni test / Seleziona file impostazioni di test, selezionato il file Local.TestSettings, quindi tutto ha funzionato.


4

Non sono sicuro che questo risponda esattamente alla domanda, ma potrebbe aiutare alcuni. Innanzitutto, ho riscontrato che la casella "Abilita distribuzione" deve essere selezionata affinché la distribuzione funzioni. In secondo luogo, il documento dice che il percorso di origine è "relativo al percorso del progetto" che inizialmente ho interpretato come la cartella del progetto. In effetti, sembra fare riferimento alla cartella di output della build. Quindi, se ho una cartella di progetto chiamata 'TestFiles' e un file in essa chiamato Testdata.xml, usare l'attributo in questo modo non funziona:

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

Posso contrassegnare il Testdata.xmlfile Copy Always, in modo che la build ne metta una copia nella cartella di output (ad esempio Debug\TestFiles\TestData.xml). Il meccanismo di distribuzione troverà quindi la copia del file situata in quel percorso ( TestFiles\Testdata.xml) relativo all'output di compilazione. Oppure posso impostare l'attributo in questo modo:

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

e il meccanismo di distribuzione troverà il file originale. Quindi entrambi funzionano, ma ho notato che usando Copy Alwaysoccasionalmente mi imbatto nello stesso problema che ho durante la modifica del file app.config in un progetto: se non cambio codice o forzo una ricostruzione, nulla attiva la copia dei file contrassegnati con essere copiato in build.


Il percorso relativo era il problema per me e questo lo ha risolto. Ho aggiunto 2 set di istruzioni DeploymentItem a seconda di come sono stati eseguiti i test.
Ed Bayiates

3

Prima ho disabilitato il flag di distribuzione. Ma anche dopo averlo abilitato, per qualche motivo sconosciuto non verrà comunque copiato nulla, nemmeno le DLL di destinazione. Accidentalmente ho aperto la finestra di esecuzione del test e ho ucciso tutte le esecuzioni precedenti e magicamente ho trovato tutte le DLL ei file di cui avevo bisogno nella cartella di test la prossima esecuzione ... Molto confuso.


2

Ho avuto enormi problemi nel tentativo di ottenere file da distribuire, provando tutti i suggerimenti sopra.

Poi ho chiuso VS2010; riavviato, caricato la soluzione e tutto ha funzionato. (!)

Ho fatto dei controlli; Dopo aver impostato il flag "Abilita distribuzione" su local.TestSetting, non dovresti semplicemente rieseguire il test dalla finestra Risultati del test. È necessario rimuovere la precedente esecuzione di test dall'interfaccia utente, ad esempio eseguendo un test diverso o riaprendo la soluzione.


2

Non usare DeploymentItem .

È molto difficile da configurare correttamente e non funzionava con il mio test runner ReSharper né con quello nativo per MSTEST in Visual Studio 2017.

Invece, fai clic con il pulsante destro del mouse sul file di dati e seleziona Proprietà . Seleziona Copia nella directory di output: Sempre .

Ora nel tuo test, fallo. La directory è semplicemente la directory del file relativo al progetto di test. Facile.

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

Questo sembra funzionare bene con sistemi di build e test automatizzati.


1

Poiché ho sempre trovato l'attributo DeploymentItem un pasticcio, eseguo la distribuzione di tali file utilizzando lo script di post-compilazione. - Assicurati che i file che desideri copiare abbiano la proprietà Copia sempre impostata. - Modifica lo script post-build del tuo progetto di test per copiare i file dalla cartella di destinazione della build (Bin \ Debug) nella posizione in cui il tuo test li aspetta.


1

Prova questo per VS2010. Quindi non è necessario aggiungere DeployItems per ogni tif
Rimuovere il file

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

Aggiungi una configurazione di prova.
- fare clic con il pulsante destro del mouse sul nodo della soluzione in Esplora soluzioni
- Aggiungi -> Nuovo elemento ...
- Selezionare il nodo Impostazioni di test a sinistra, selezionare l'elemento a destra
- Fare clic su Aggiungi

Chiamalo ad es TDD

Scegli TDDsotto TestMenu>Edit Testsettings .

Fare clic sulla distribuzione. Abilitalo e poi aggiungi i file e le directory che desideri. Ci sarà un percorso relativo alla soluzione. I file verranno inseriti. I file originali sono ad esempio qui:

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

Quando eseguo il mio unit test, viene copiato in

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  

in testcode lo chiamo da:

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

Non è necessario scegliere Copia sempre; mettere i file nel testproject; aggiungere percorsi hardcoded nel codice di prova. Per me questa soluzione ha funzionato meglio. Ho provato con DeploymentItem, copia sempre ma non era di mio gradimento.


1

Per coloro che preferiscono evitare il caos di DeploymentItem e adottare l'approccio suggerito da @Martin Peck (risposta accettata), è possibile utilizzare il seguente codice per accedere ai contenuti della risorsa incorporata:

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();
    }
}

Per i dettagli, vedere questo thread SO


1
Ho avuto problemi con Assembly.GetExecutingAssembly () durante l'esecuzione su un server di compilazione -> restituirebbe il test runner invece dell'effettivo assembly di test. Ottenere l'assieme riflettendolo su un tipo fisso nel gruppo di prova (ad esempio la tua classe di prova) ha risolto il problema per me.
Arno Peters

1

Per me, la causa principale era qualcosa di completamente diverso: il codice di produzione utilizzato dai miei test stava rinominando e / o eliminando il file di test .xml distribuito.

Pertanto, quando eseguivo i miei test individualmente, passavano, ma quando li eseguivo tutti insieme, il secondo e il successivo test fallivano con errori di "file non trovato" (che inizialmente avevo erroneamente diagnosticato come l' DeploymentItemattributo non funzionante).

La mia soluzione era quella di fare in modo che ogni singolo metodo di test facesse una copia del file distribuito (utilizzando questa tecnica ), quindi fare in modo che il codice di produzione in fase di test utilizzasse il file copiato anziché l'originale.


1

Abbiamo speso molto tempo per risolvere il problema degli elementi di distribuzione per risolverlo in unittest run locale e anche in teamcity unittest. Non è facile.

Un ottimo strumento per eseguire il debug di questo problema è ProcessExplorer . Utilizzando Process Explorer, puoi controllare dove si trova Visual Studio alla ricerca degli elementi di distribuzione e apportare la correzione al progetto. Filtra tutte le operazioni sui file in cui il percorso contiene il nome del file dell'elemento di distribuzione e lo vedrai.


So che questa è una risposta molto vecchia, ma se sei in grado di approfondire come usi ProcessExplorer, sarebbe utile. Non vedo affatto come visualizzare le operazioni sui file, tanto meno filtrarle ...
David

1

Oltre all'attributo Deployment che deve essere controllato, ho scoperto qualcos'altro sull'attributo DeploymentItem.

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

Il file deploymentFile.txt deve essere relativo al file della soluzione e non a testfile.cs.

inserisci qui la descrizione dell'immagine


Alla fine ho ottenuto questo funzionamento avendo la mia fonte DeploymentItem relativa al progetto di test. Quindi ho un progetto nella mia soluzione, "Service.Tests". Là sotto ho una cartella "FilesForTests" che contiene i file che voglio copiare. Ho usato [DeploymentItem(@"FilesForTests\MyFile.txt", "FilesForTests")]. Io penso che stiamo dicendo la stessa cosa?
David

1

Ci ho lavorato in VS2013. I miei risultati per farlo funzionare:

  • Copia nella directory di output deve essere impostata su Copia se più recente / Copia sempre: OBBLIGATORIO.
  • "Abilita distribuzione" in .TestSettings: NON RICHIESTO. Ho funzionato senza un file .TestSettings.
  • Specificare una cartella come 2 ° parametro: FACOLTATIVO. Modella il layout della cartella di output, funziona bene senza.
  • SPAZI nel nome del file: questo mi ha causato mal di testa - il file non è mai stato copiato. La rimozione degli spazi ha risolto questo problema. Non ho ancora esaminato i personaggi di fuga.

Un consiglio che ho imparato anche a mie spese: non dimenticare di aggiungere questo attributo a ogni singolo test. Il file viene copiato nel primo test attribuito nel testrun, ma è rimasto mancante quando l'ordine dei test è cambiato e i test non attribuiti hanno tentato di trovare prima il file.


Ho provato tutto qui prima di arrivare alla tua risposta che era l'ultima. Il colpevole: SPAZI NEL FILENAME! Buon callout.
joelmdev

1
Utilizzando Visual Studio 2019. "Copia se più recente" ha risolto il problema. Odio "Copia sempre" perché costringe il progetto a ricostruire su molti scenari come il debug o la build incrementale.
Gerardo Grignoli

Concordato. Ho aggiornato la mia risposta per includere Copia se più recente.
Arno Peters

0

Il mio grande "trucco" era il modo in cui DeploymentItem gestisce le directory. Stavo usando la versione a due parametri con entrambi come percorso della directory contenente le sottodirectory che volevo distribuire. Inizialmente non mi ero reso conto che copia solo le cose nella ROOT della directory e non l'intera struttura delle cartelle ricorsive!

Fondamentalmente avevo [DeploymentItem (@ "Foo \", @ "Foo \")] e mi aspettavo che distribuisse il mio Foo \ Bar. Ho dovuto specificatamente cambiarlo in [DeploymentItem (@ "Foo \ Bar \", @ "Foo \ Bar \")] e ora funziona a meraviglia.


0

Ho anche affrontato problemi simili. Ho tutti i passaggi sopra menzionati ma ancora senza fortuna. Sto usando VS2010. Quindi ho scoperto che è stato selezionato $ Menu> Test> Seleziona impostazione test attivo> Traccia e prova impatto . Ha iniziato a funzionare dopo aver modificato Trace e test impact in Local . Questa pagina contiene informazioni molto piene di risorse sulla copia dei file nella cartella dei risultati dei test, mi sento di aggiungere anche questa esperienza.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.