2010-07-20 13 views
12

Mam niektóre funkcje, które czytają & modyfikować pliki. Aby testy jednostki były niezależne od problemów związanych z systemem plików, chcę dołączyć pliki do projektu.W tym plik zasobów dla testu jednostki w projekcie C#

Jednak moja funkcja powinna uzyskiwać ścieżkę filePath, a wszystko, co mogę uzyskać ze złożenia, to FileStream. Masz pomysł, jak uzyskać ścieżkę do pliku zasobów w projekcie?

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

Dzięki!

+1

IMHO takie dane testowe nie powinny być wbudowane w teście i powinny być dostarczane osobno (co pozwala także ponownie uruchomić test z różnych danych bez przebudowy). Jakich problemów z systemem plików martwisz? –

+2

Nie podoba mi się, że testy jednostek zależą od zasobów zewnętrznych, które można zmieniać, przenosić, zmieniać itd. Ten test jednostkowy jest wykonywany w celu sprawdzenia 1 scenariusza i chcę, aby ten dokładny scenariusz był testowany, więc powinien być niezależny od tego, czy uprawnienia do pliku mogą zostać zmienione, zbyt wiele programów do obsługi plików jest otwartych, dysk NTFS jest niedostępny i tak dalej. – Yossale

+0

Myślę, że to bardzo dobre pytanie. Jeśli chodzi o rzeczywiste testy jednostkowe, to przyznaję, że należy unikać używania plików, ale jeśli pomyślimy o testach integracyjnych (np. Obecnie piszę czytnik plików), używając "prawdziwych" danych testowych ma sens imho. – anhoppe

Odpowiedz

8

Moje zwykłe rozwiązanie tego problemu polega na tym, że pomnożę mój program, aby otworzyć plik w metodzie wywołującej, a następnie przekazać strumień zamiast podać nazwę pliku i otworzyć tam plik.

Do testowania pozwala mi to przekazać MemoryStream, więc mogę napisać test jednostki bez użycia systemu plików. Czasem nawet łatwiej jest sprawdzić, czy dane zostały napisane poprawnie i jest zdecydowanie szybciej, szczególnie w przypadku większej liczby testów. Trzeba tylko pamiętać, aby wypróżnić MemoryStream po napisaniu, ponieważ .NET nie zawsze robi to automatycznie.

Przykład jednego z moich programów:

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. Nie podobały mi się te wszystkie strumienie, a to wygląda na dobre rozwiązanie. – Yossale

0

Jeśli ustawisz akcję kompilacji pliku do skopiowania, możesz wtedy przewidzieć, gdzie plik ma być (prawdopodobnie kilka ... \ .. \ .. \, ale nadal). Zgaduję, że masz dane wejściowe dotyczące metody dla nazwy pliku, więc powinno to działać dobrze.

Czy jest to sugestia, czy możliwe jest wykreślenie faktycznego odczytu/zmiany tego pliku w metodę i przekazanie wartości ciągu? Jedynym powodem, dla którego to przedstawię, jest to, że pachnie jak test integracyjny (dotykając systemu plików).

4

Osadzony zasób nie istnieje w systemie plików, więc nie ma ścieżki do pliku.

Masz dwie opcje:

  • zmienić API swojego SUT tak, że przyjmuje Stream zamiast tylko ścieżkę do pliku. To rozwiązanie jest znacznie preferowane.
  • Zapisz osadzony zasób w pliku tymczasowym podczas testowania urządzenia, pamiętając o usunięciu go ponownie po każdym przypadku testowym.

Pierwsze rozwiązanie jest doskonałym przykładem tego, jak TDD kieruje nas w stronę lepszych, bardziej elastycznych interfejsów API.

+0

Zacząłem od Streama dookoła, ale czułem, że żongluję wieloma otwartymi pilotami w powietrzu. Ale zastanowiłabym się przez chwilę. Dzięki. – Yossale

+1

Zawsze można tworzyć przeciążone metody: jedna, która pobiera ścieżkę pliku, ale tak naprawdę przekazuje tylko drugą, która pobiera strumień ... –

1

Można ustawić pliki danych, które mają zostać skopiowane do katalogu bin, gdy projekt zostanie zbudowany, a następnie odnieść je za pomocą Directory.GetCurrentDirectory() do testu. Lub nawet pozostawić je tam, gdzie są i po prostu użyć względnej ścieżki na podstawie bieżącego katalogu.

Lepiej byłoby jednak zrestrukturyzować kod, aby opierał się na klasie Stream, a następnie użyć kombinacji szyderstwa i zastrzyku zależności, aby dostarczyć fałszywego strumienia z danymi - lub użyć strumienia pamięci, jeśli fałszowanie działa lepiej.

+1

Niektóre programy testowe nie mają katalogu bin jako bieżącego katalogu podczas uruchamiania testu. Użyj 'AppDomain.CurrentDomain.BaseDirectory', aby uzyskać katalog wdrażania, a nie' Directory.GetCurrentDirectory() '. – Sjoerd

Powiązane problemy