Jak przetestować czytnik plików?

19

Pracuję nad projektem z kilkoma formatami plików. Niektóre formaty są określone przez .xsds, inne przez dokumentację na ich stronach internetowych, a niektóre są niestandardowymi formatami wewnętrznymi, które nie mają dokumentacji. Mwahahahaha.

Jaki jest problem?

Chciałbym przetestować moje czytniki plików, ale nie jestem do końca pewien, jak to zrobić. Przepływ aplikacji jest taki:

file.___  ===> read by FileReader.java ===> which creates a Model object

gdzie FileReaderjest interfejs

public interface FileReader {
    public Model read(String filename);
}

ModelMa wiele atrybutów, które są wypełniane, gdy plik jest odczytywany. To wygląda jak

public class Model {
    List<String> as;
    List<String> bs;
    boolean isAPain = true;
    // ...
}

Co próbowałem?

Moim jedynym pomysłem było stworzenie „generatorów” plików dla każdego formatu pliku. Generatory te są w zasadzie konstruktorami, które pobierają kilka zmiennych (np. Liczbę komentarzy do wygenerowania w pliku) i generują przykładowy plik, który następnie czytam i porównuję uzyskane wyniki Modelze zmiennymi, których użyłem do początkowego wygenerowania pliku.

Ma to jednak kilka problemów:

  • Pliki, które generuje, nie wyglądają jak prawdziwe pliki. Generator nie jest w żaden sposób świadomy kontekstu.
  • Trudno rozpoznać, czy generator wygenerował dla przypadków krawędzi, ponieważ to ja ręcznie ustawiam zmienne. Ta metoda jest niewiele lepsza niż ja, tworząc kilkanaście przykładowych plików.

Czy są na to lepsze sposoby?

EDYCJA: Zmieniłem jednostkę na integrację, ponieważ tak właśnie mam na myśli.

EDIT2: Oto przykład przypadków krawędzi, o których wspomniałem.

Każdy plik reprezentuje wykres złożony z wierzchołków i krawędzi. Te wierzchołki i krawędzie można dołączyć na różne sposoby, więc:

v1 -- e1 --> v2 <-- e2 -- v3

jest inny od

v1 -- e1 --> v2 -- e2 --> v3

w tym kierunku znaczenie mają krawędzie. Nie jestem pewien, czy jest to objęte pytaniem, ale trudno jest wymyślić wszystkie istotne przypadki krawędzi, gdy ręcznie ustawiam liczbę wierzchołków, liczbę krawędzi i po prostu generuję połączenia losowo.

sdasdadas
źródło
1
Przychodzą mi na myśl testy oparte na danych. Czy możesz podać konkretne przykłady przypadków skrajnych (w oparciu o przypadki skrajne, które mogłyby zostać uruchomione w rzeczywistej FileReaderimplementacji)? Przykład: biorąc pod uwagę przypadki krawędzi znalezione w formatach plików obrazów , dla każdego wpisu tabeli, jeśli obsługiwana jest kombinacja właściwości wiersz / kolumna, powinien istnieć co najmniej jeden przypadek testowy (plik danych) obejmujący tę kombinację.
rwong
@rwong Dodałem przykład, ale nie jestem pewien, czy to daje pomysł. Myślę, że mój problem jest powszechny w przypadku przypadków skrajnych, tj. Czy coś przegapiłem? Chociaż testy oparte na danych wyglądają interesująco. Dzięki!
sdasdadas
7
Właśnie to zauważyłem, ale moje przypadki krawędzi dosłownie są przypadkami krawędzi .
sdasdadas
1
Dlaczego nie wykonać ręcznie plików testowych, a następnie zawsze uruchamiać te same pliki?
Bobson
@ Bobson To trochę gorzej niż przy użyciu generatora. W takim przypadku mogę pominąć przypadki krawędzi (jak teraz pewnie mi brakuje), ale mogę również wprowadzić błędy w pisaniu. A przy dużych plikach samodzielne ich tworzenie zajęłoby sporo czasu.
sdasdadas

Odpowiedzi:

19

Najpierw porozmawiajmy o twoich celach:

  • oczywiście nie chcesz testować „formatów plików” - chcesz przetestować różne FileReaderimplementacje

  • chcesz znaleźć jak najwięcej różnych rodzajów błędów w testach automatycznych

Aby w pełni osiągnąć ten cel, IMHO musisz połączyć różne strategie:

  • po pierwsze, prawdziwe testy jednostkowe: twoje FileReaderwdrożenia będą się składać z wielu różnych części i funkcji. Napisz małe testy, które testują każdy z nich osobno; zaprojektuj swoje funkcje tak, aby nie musiały tak naprawdę odczytywać danych z pliku. Tego rodzaju testy pomogą ci przetestować większość twoich skrajnych przypadków.
  • po drugie, generowane pliki: to właśnie nazwałbym testami integracji. Takie pliki pomogą Ci wyśledzić awarie inne niż w punkcie 1, na przykład kombinacje określonych parametrów, błędy w dostępie do plików itp. Aby stworzyć dobre przypadki testowe, pomocne będzie również zapoznanie się z niektórymi klasycznymi technikami, takimi jak grupowanie przypadków testowych w klasy równoważności lub badanie wartości granicznej. Zdobądź kopię tej książki autorstwa Glenford Myers, aby dowiedzieć się więcej na ten temat. Artykuł w Wikipedii na temat testowania oprogramowania jest również dobrym źródłem.
  • po trzecie, spróbuj uzyskać rzeczywiste dane: może być trudno zweryfikować, czy te pliki są poprawnie ocenione przez twoje FileReader, ale może to być tego warte, ponieważ często stwierdza błędy, które nie są ujawniane przez dwie pierwsze strategie. Niektórzy nazywają takie rzeczy „testami integracji”, inni wolą „testy akceptacji”, ale tak naprawdę termin ten nie ma znaczenia.

IMHO nie ma podejścia „skrótowego”, które przyniosłoby korzyści wszystkim trzem strategiom „za cenę jednej”. Jeśli chcesz wykrywać przypadki awaryjne, a także awarie w przypadkach standardowych i rzeczywistych, musisz zainwestować przynajmniej trochę - prawdopodobnie dużo - wysiłku. Na szczęście wszystkie te podejścia można wykorzystać do tworzenia automatycznych, powtarzalnych testów.

Poza tym powinieneś upewnić się, FileReaderże nie maskujesz żadnych błędów podczas odczytywania tych danych - twórz wbudowane kontrole / asercje, zgłaszaj wyjątki, gdy coś pójdzie nie tak wewnętrznie itp. To daje twojemu kodowi testowemu znacznie większą szansę na wykrycie błędów , nawet jeśli nie masz jawnego pliku testowego lub przypadku testowego na nieoczekiwaną sytuację.

Doktor Brown
źródło
Niesamowita odpowiedź, a ja zmienię tytuł mojego pytania, aby lepiej się zastanowić. Dzięki!
sdasdadas