Problemy z atrybutem DeploymentItem

94

Obecnie zajmuję się "starym" systemem napisanym w C # .net, usuwając niektóre przestarzałe funkcje i dokonując pewnych refaktoryzacji. Dzięki Bogu, poprzedni facet napisał kilka testów jednostkowych (MSTests). Dość dobrze czuję się z testami JUnit, ale nie zrobiłem jeszcze wiele z MSTestami.

Metody testowe mają DeploymentItematrybut określający plik tekstowy, który jest analizowany przez testowaną metodę logiki biznesowej, oraz drugi, w DeploymentItemktórym określono tylko ścieżkę, zawierającą kilka plików TIF, które również muszą zostać wdrożone.

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

Wcześniej testy działały, ale teraz musiałem zmienić nazwy plików TIF zawartych w katalogu \ files \ tif. Zgodnie z zasadą nazwy plików TIF muszą pasować do określonego wzorca, który jest również sprawdzany ExistsTifTest()metodą. Teraz musiałem zmienić nazwy plików, aby dostosować je do nowych wymagań i nagle pliki TIF nie są już wdrażane jak wcześniej.

Czy ktoś może mi podpowiedzieć, dlaczego tak się dzieje lub co może być tego przyczyną? To samo dzieje się również, gdy dodam nowy plik tekstowy, mówiąc „my2ndTest.txt” obok „valid_entries.txt” w katalogu \ files \ valid \ z odpowiednim atrybutem DeploymentItem w metodzie testowej. Plik nie został wdrożony?

Obrazy zostały już wdrożone, definiując ścieżkę wdrażania bezpośrednio w pliku testrunconfig, ale chciałbym zrozumieć, dlaczego takie rzeczy się zdarzają lub dlaczego, na przykład, mój nowy plik „my2ndTest.txt” nie jest wdrażany, podczas gdy inne.

Juri
źródło
2
Dużym problemem jest uświadomienie sobie, że wszystkie elementy określone w DeploymentItemAttribute zostaną skopiowane do lokalizacji, z której są uruchamiane zestawy testowe. Innymi słowy, jeśli miałeś nadzieję, że zachowa on strukturę katalogów, nie będziesz miał szczęścia. Jeśli chcesz, aby została skopiowana do określonego katalogu, użyj wersji z dwoma parametrami DeploymentItem (source, outputDir). FYI - możesz przejść do starej szkoły, aby dowiedzieć się, gdzie są uruchamiane pliki dla MsTest, upuszczając System.Console.WriteLine (System.Environment.CurrentDirectory) do jednego z testów. NCrunch nie miał tego problemu!
CodeMonkeyKing

Odpowiedzi:

112

DeploymentItem jest trochę bałaganu.

Każdy plik w rozwiązaniu będzie miał ustawienie „Kopiuj do folderu wyjściowego” w VS.NET. Musisz mieć ustawienie „Zawsze kopiuj” (lub podobne), aby pobrać pliki do folderu wyjściowego.

Sprawdź, czy masz ten zestaw dla nowych plików. Jeśli nie masz tego zestawu, pliki nie zostaną skopiowane do folderu wyjściowego, a następnie nie można ich wdrożyć z folderu wyjściowego do folderu, w którym MSTest to robi.

Osobiście, jeśli mam pliki, których potrzebuję do testów jednostkowych, stwierdziłem, że osadzanie tych plików jako zasobów w zestawie i samodzielne „rozpakowywanie” zestawu podczas testów jest bardziej przewidywalnym sposobem działania. YMMV.

Uwaga: Te komentarze są oparte na moich doświadczeniach z VS2010. Komentarze do mojej odpowiedzi sugerują, że nie jest to problem z VS2012. Wciąż trzymam się komentarzy, że używanie zasobów osadzonych wymaga mniej „magii” i, dla mnie, sprawia, że ​​etap „aranżacji” moich testów jednostkowych jest znacznie bardziej wyraźny.

Martin Peck
źródło
3
Kopiuj do katalogu wyjściowego nigdy nie wpływa na sposób wdrażania plików przez MSTest. Ta odpowiedź jest nieprawidłowa.
kzu
19
W VS2010 Premium wprowadzenie tej zmiany (i żadnej innej zmiany) spowodowało wdrożenie pliku. W związku z tym wnioskuję na podstawie rzeczywistych dowodów, że ma to wpływ na wdrożenie MsTest.
JonStonecash
1
Zgoda. Widziałem tę pojedynczą zmianę, gdy DeploymentItem marszczy się do góry nogami.
Martin Peck
2
Wydaje się, że nie jest to już wymagane w VS2012. Moje elementy stanowiska są wdrażane z opcją „Kopiuj do folderu wyjściowego” ustawioną na „Nie kopiuj”.
Mike
31
To wspaniałe, że DeploymentItem nie powiadamia Cię, gdy nie może skopiować pojedynczego pliku, który go dostarczyłeś.
74

W VS2010 mój Local.testsettings miał odznaczoną opcję „Włącz wdrażanie”, a atrybut DeploymentItem nie działał. Sprawdziłem to i wszystko działało dobrze. Mam nadzieję, że to pomoże!

Ivan Muzzolini
źródło
2
Od wieków walę głową w ceglaną ścianę, próbując zmusić ją do działania ... dziękuję!
mat-mcloughlin
12
Myślę, że byłoby miło, gdyby platforma wydała ostrzeżenie, że atrybuty DeploymentItem są ignorowane, jeśli to ustawienie jest wyłączone. Zrobiłem też ładne wklęsłe wrażenie na biurku.
Alan McBee - MSFT
2
Zwróć uwagę, że Local.testsettings znajduje się w pozycji rozwiązania
Matthew Lock
Musiałem również dodać katalog zawierający elementy, które chciałem wdrożyć do Local.testsettings również: i.imgur.com/p1z3m9R.png
Matthew Lock
Korzystanie z VS2017 w 2018 roku, zaznaczenie opcji „Włącz wdrażanie” jest nadal rozwiązaniem tego problemu. I niestety nadal ostrzegam przed Visual Studio. Dzięki za to rozwiązanie.
Don H
19

Miałem również podobne problemy, ale znalazłem łatwe 3-stopniowe rozwiązanie tego problemu:

Zakładając, że struktura folderów wygląda następująco: SolutionFolder\ TestProjectFolder\ SubFolder\

  1. Przejdź do „Solutions Items / Local.testsettings”> „Deployment”> zaznacz „Enable Deployment”
  2. Jeśli używasz VS2010, upewnij się, że wszystkie pliki, które chcesz wdrożyć, mają właściwość „Kopiuj do folderu wyjściowego” ustawioną na „Kopiuj zawsze” lub „Kopiuj, jeśli nowszy”
  3. Przypisz parametr TestMethod jedną z następujących opcji:
    • [DeploymentItem(@"TestProjectFolder\SubFolder")]aby wdrożyć całą zawartość w <SubFolder>katalogu Test Run
    • [DeploymentItem(@"TestProjectFolder\SubFolder", "TargetFolder")] wdrożyć całą zawartość <SubFolder>do <TargetFolder>w katalogu próbny

Ostatnia uwaga na temat MSTest (przynajmniej dla VS2010):

Jeśli chcesz, <TargetFolder>aby miało taką samą nazwę jak the <SubFolder>, użycie [DeploymentItem(@"SubFolder", @"SubFolder")]zakończy się niepowodzeniem, gdy biegacz MSTest trafi w głupi przypadek krawędzi. Dlatego należy poprzedzić <SubFolder>z <TestProjectFolder>jak tak:[DeploymentItem(@"TestProjectFolder\SubFolder", @"SubFolder")]

Murari Kumar
źródło
Uwaga o niepowodzeniu nazewnictwa podfolderów to perełka.
RJ Lohan
1
VS 2015 wydaje się być trochę inny. Musiałem usunąć część „TestPojectFolder” w atrybucie DeploymentItem.
uli78
15

Miejmy nadzieję, że pomogę komuś innemu: wypróbowałem wszystkie sugestie tutaj i nadal mój element rozmieszczenia nie był kopiowany.

To, co musiałem zrobić ( zgodnie z sugestią tutaj ), to dodać drugi parametr do atrybutu DeploymentItem:

[DeploymentItem(@"UnitTestData\TestData.xml", "UnitTestData")]
Peter K.
źródło
10

Jeśli przejdziesz do pliku .testrunconfig i podczas wdrażania odznacz „Włącz wdrażanie”, testy będą działać w ich normalnej lokalizacji i wszystko będzie działać tak, jak w przypadku uruchamiania aplikacji poza testem jednostkowym.

Josh Close
źródło
Miałem też z tym pewne problemy. Jako PM nie mam dostępu do wszystkich narzędzi używanych przez dev. W tym przypadku ReSharper skopiował plik poprawnie, podczas gdy MSTest nie mógł tego zrobić. -> Wystąpiły błędy, gdy programowanie było OK. Zmień na „Testuj-> Edytuj ustawienia testu -> Ustawienia lokalne -> Wdrażanie”, w tym plik, o którym mowa, naprawił to dla mojego użycia MSTest.
sonstabo
9

Prawdopodobnie nie ma to związku z konkretnym problemem, ale oto kilka wskazówek, które znalazłem z atrybutem [DeploymentItem].

  1. Kopiuj do katalogu wyjściowego należy ustawić na Zawsze kopiuj.

Robi nie działa, gdy używany z atrybutem [TestInitialize]

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

Powinien znajdować się na twoim [TestMethod], np

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

    [TestMethod]
    [DeploymentItem("test.xlsx")]
    public void ExcelQuestionParser_Reads_XmlElements()
    {
        ...
    }
Matt Frear
źródło
1
To szalenie irytujące ograniczenie. Wydaje mi się, że w wielu przypadkach czas na wdrożenie powinien być w Initialize. A jeśli wszystkie moje testy używają tych samych artefaktów pomocniczych? Myślę, że mam kopiować i wklejać dekoratory w dziesiątkach metod testowych? Śmieszny.
Ryanman
5

Po wypróbowaniu wszystkich innych wymienionych tutaj sugestii nadal nie mogłem dowiedzieć się, co się dzieje. W końcu odkryłem, że w menu Test / Test Settings nie wybrano żadnego pliku ustawień, co oznaczało, że Wdrażanie nie było włączone. Kliknąłem opcję Test / Test Settings / Select Test Settings File, wybrałem plik Local.TestSettings i wszystko działało.

Mikrofon
źródło
4

Nie jestem pewien, czy to dokładnie odpowiada na pytanie, ale może niektórym pomóc. Najpierw stwierdziłem, że pole „Włącz wdrożenie” musi być zaznaczone, aby wdrożenie działało. Po drugie, dokument mówi, że ścieżka źródłowa jest „względna w stosunku do ścieżki projektu”, co na początku oznaczało folder projektu. W rzeczywistości wydaje się, że odnosi się do folderu wyjściowego kompilacji. Więc jeśli mam folder projektu o nazwie `` TestFiles '' i plik w nim o nazwie Testdata.xml, użycie atrybutu w ten sposób nie działa:

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

Mogę oznaczyć Testdata.xmlplik Copy Always, aby kompilacja umieściła kopię w folderze wyjściowym (np Debug\TestFiles\TestData.xml.). Mechanizm wdrażania znajdzie wtedy kopię pliku znajdującą się w tej path ( TestFiles\Testdata.xml) względem wyniku kompilacji. Albo mogę ustawić atrybut w ten sposób:

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

a mechanizm wdrażania znajdzie oryginalny plik. Więc albo działa, ale zauważyłem, że używając Copy Alwaysczasami napotykam ten sam problem, który mam podczas edycji pliku app.config w projekcie - jeśli nie zmienię kodu lub nie wymuszę przebudowy, nic nie uruchamia kopiowania plików oznaczonych do być kopiowane w kompilacji.

user1546704
źródło
Względna ścieżka była dla mnie problemem i to go rozwiązało. Dodałem 2 zestawy instrukcji DeploymentItem w zależności od sposobu uruchomienia testów.
Ed Bayiates
3

Najpierw wyłączono flagę wdrażania. Ale nawet po włączeniu tej funkcji z jakiegoś nieznanego powodu nic, nawet docelowy plik DLL, nie zostałoby skopiowane. Przypadkowo otworzyłem okno Test Run i zabiłem wszystkie poprzednie uruchomienia i magicznie znalazłem wszystkie biblioteki DLL i pliki, których potrzebowałem w folderze testowym przy następnym uruchomieniu ... Bardzo mylące.

Schultz9999
źródło
2

Miałem ogromne problemy podczas próby udostępnienia plików - wypróbowałem wszystkie powyższe sugestie.

Następnie zamknąłem VS2010; uruchomiłem go ponownie, załadowałem rozwiązanie i wszystko działało. (!)

Sprawdziłem trochę; Po ustawieniu flagi „Włącz wdrożenie” na local.TestSetting nie należy po prostu ponownie uruchamiać testu z okna Wyniki testu. Musisz usunąć poprzednie uruchomienie testowe z interfejsu użytkownika, np. Uruchamiając inny test lub ponownie otwierając rozwiązanie.

Stephen Westlake
źródło
2

Nie używaj DeploymentItem.

Jest bardzo trudny do poprawnej konfiguracji i nie działał z moim uruchomieniem testowym ReSharper ani natywnym dla MSTEST w Visual Studio 2017.

Zamiast tego kliknij prawym przyciskiem myszy plik danych i wybierz właściwości . Wybierz opcję Kopiuj do katalogu wyjściowego: zawsze .

Teraz w swoim teście zrób to. Katalog to po prostu katalog pliku odnoszący się do projektu testowego. Łatwo.

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

Wydaje się, że działa to dobrze w przypadku zautomatyzowanych systemów kompilacji i testowania.

Pęto
źródło
1

Ponieważ atrybut DeploymentItem zawsze był dla mnie bałaganem, wdrażam takie pliki za pomocą skryptu po kompilacji. - Upewnij się, że pliki, które chcesz skopiować, mają ustawioną właściwość Zawsze kopiuj. - Zmodyfikuj skrypt po kompilacji projektu testowego, aby skopiować pliki z folderu docelowego kompilacji (Bin \ Debug) do lokalizacji, w której oczekuje ich test.

Ismail Hawayel
źródło
1

Wypróbuj to dla VS2010. Nie musisz więc dodawać DeployItems dla każdego tif.
Usuń rozszerzenie

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

Dodaj konfigurację testową.
- kliknij prawym przyciskiem myszy węzeł rozwiązania w eksploratorze rozwiązań
- Dodaj -> Nowy element ...
- Wybierz węzeł Ustawienia testu po lewej stronie, wybierz element po prawej stronie
- Kliknij Dodaj

Nazwij to np TDD

Wybierz TDDponiżej TestMenu> Edit Testsettings.

Kliknij Wdrożenie. Włącz go, a następnie dodaj żądane pliki i katalogi. Pojawi się ścieżka względna do rozwiązania. Pliki zostaną założone. Oryginalny plik jest na przykład tutaj:

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

Kiedy uruchamiam mój test jednostkowy, jest on kopiowany do

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  

w kodzie testowym dzwonię z:

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

Nie ma potrzeby wybierania opcji Zawsze kopiuj; umieścić pliki w testproject; dodaj zakodowane na stałe ścieżki w kodzie testowym. U mnie to rozwiązanie sprawdziło się najlepiej. Próbowałem z DeploymentItem, kopiuj zawsze, ale nie podobało mi się.

Patrik Lindström
źródło
1

Dla tych, którzy wolą uniknąć bałaganu DeploymentItem i zastosować podejście sugerowane przez @Martin Peck (zaakceptowana odpowiedź), możesz użyć następującego kodu, aby uzyskać dostęp do zawartości osadzonego zasobu:

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

Aby uzyskać szczegółowe informacje, zobacz ten wątek SO

Sudhanshu Mishra
źródło
1
Miałem problemy z Assembly.GetExecutingAssembly () podczas uruchamiania na serwerze kompilacji -> zwróciło to runner testowy zamiast rzeczywistego zestawu testowego. Uzyskanie złożenia przez odbicie go od ustalonego typu w zestawie testowym (na przykład twoja klasa testowa) rozwiązało to za mnie.
Arno Peters
1

Dla mnie główną przyczyną było coś zupełnie innego: kod produkcyjny wykonywany przez moje testy zmieniał nazwę i / lub usuwał wdrażany plik testowy .xml.

Dlatego, gdy uruchamiałbym moje testy indywidualnie, przeszłyby, ale podczas uruchamiania ich wszystkich razem, drugi i kolejny test kończyłby się niepowodzeniem z błędem „nie znaleziono pliku” (który pierwotnie błędnie zdiagnozowałem jako DeploymentItematrybut niedziałający).

Moje rozwiązanie polegało na tym, aby każda metoda testowa tworzyła kopię wdrożonego pliku (przy użyciu tej techniki ), a następnie testowany kod produkcyjny używał skopiowanego pliku zamiast oryginału.

Jon Schneider
źródło
1

Spędziliśmy dużo czasu, rozwiązując problem z elementami rozmieszczania w lokalnych rozgrywkach Unittest i Teamcity Unittest. To nie jest łatwe.

Bardzo dobrym narzędziem do debugowania tego problemu jest ProcessExplorer . Korzystając z eksploratora procesów, możesz sprawdzić, gdzie jest program Visual Studio wyszukujący elementy wdrożenia i wprowadzić poprawki w projekcie. Po prostu odfiltruj wszystkie operacje na plikach, w których ścieżka zawiera nazwę pliku elementu wdrożenia, a zobaczysz go.

Tomas Kubes
źródło
Wiem, że to bardzo stara odpowiedź, ale jeśli jesteś w stanie wyjaśnić, jak używasz ProcessExplorer, byłoby to pomocne. W ogóle nie widzę, jak przeglądać operacje na plikach, a tym bardziej je filtrować ...
David,
1

Oprócz atrybutu Deployment, który należy sprawdzić, odkryłem jeszcze coś na temat atrybutu DeploymentItem.

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

Twój plik deploymentFile.txt musi być względny w stosunku do pliku rozwiązania, a nie do pliku testfile.cs.

wprowadź opis obrazu tutaj

Pavenhimself
źródło
W końcu udało mi się to zadziałać, ponieważ moje źródło DeploymentItem jest względne do projektu testowego. Mam więc w swoim rozwiązaniu projekt „Service.Tests”. Tam mam folder „FilesForTests”, w którym znajdują się pliki, które chcę skopiować. Użyłem [DeploymentItem(@"FilesForTests\MyFile.txt", "FilesForTests")]. Myślę, że mówimy to samo?
David
1

Pracowałem nad tym w VS2013. Moje ustalenia, aby to działało:

  • Kopiuj do katalogu wyjściowego należy ustawić na Kopiuj, jeśli nowsze / Kopiuj zawsze: OBOWIĄZKOWE.
  • „Włącz wdrażanie” w .TestSettings: NIE WYMAGANE. Mam to działające bez pliku .TestSettings w ogóle.
  • Określanie folderu jako drugiego parametru: OPCJONALNIE. Kształtuje układ folderu wyjściowego, działa dobrze bez.
  • SPACES w nazwie pliku: przyprawiło mnie to o ból głowy - plik nigdy nie został skopiowany. Usunięcie spacji naprawiło ten problem. Nie zajrzałem jeszcze do postaci ucieczki.

Wskazówka, której też nauczyłem się na własnej skórze: nie zapomnij dodać tego atrybutu do każdego testu. Plik kopiuje się z pierwszego przypisanego testu w trakcie testu, ale nadal go brakowało, gdy kolejność testów uległa zmianie, a testy bez przypisania próbowały najpierw znaleźć plik.

Arno Peters
źródło
Wypróbowałem wszystko tutaj, zanim dotarłem do ostatniej odpowiedzi. Sprawca: spacje w nazwie pliku! Dobre objaśnienie.
joelmdev
1
Korzystanie z programu Visual Studio 2019. „Kopiuj, jeśli nowszy” - naprawił problem. Nienawidzę opcji „Zawsze kopiuj”, ponieważ wymusza ona przebudowę projektu w wielu scenariuszach, takich jak debugowanie lub kompilacja przyrostowa.
Gerardo Grignoli
Zgoda. Zaktualizowałem odpowiedź, dodając opcję Kopiuj, jeśli nowsza.
Arno Peters,
0

Moją wielką łapą był sposób, w jaki DeploymentItem obsługuje katalogi. Używałem wersji z dwoma parametrami, w których oba były ścieżką katalogu zawierającą podkatalogi, które chciałem wdrożyć. Początkowo nie zdawałem sobie sprawy, że kopiuje tylko zawartość katalogu głównego, a nie całą rekursywną strukturę folderów!

Zasadniczo miałem [DeploymentItem (@ "Foo \", @ "Foo \")] i spodziewałem się, że wdroży mój Foo \ Bar. Specjalnie musiałem zmienić to na [DeploymentItem (@ "Foo \ Bar \", @ "Foo \ Bar \")] i teraz działa jak urok.

StalePhish
źródło
0

Ja też miałem podobne problemy. Mam wszystkie wymienione powyżej kroki, ale nadal nie mam szczęścia. Używam VS2010. Następnie stwierdziłem, że wybrano $ Menu> Test> Wybierz ustawienia aktywnego testu> Śledź i testuj wpływ . Zaczęło działać po zmianie śledzenia i przetestowaniu wpływu na lokalny . Ta strona zawiera bardzo przydatne informacje na temat kopiowania plików do folderu wyników testów. Czuję, że mogę dodać to doświadczenie.

MJK
źródło