Jak mogę przetestować jednostkowo GUI?

154

Obliczenia w moim kodzie są dobrze przetestowane, ale ponieważ jest tak dużo kodu GUI, moje ogólne pokrycie kodu jest mniejsze niż bym chciał. Czy są jakieś wytyczne dotyczące kodu GUI do testów jednostkowych? Czy to w ogóle ma sens?

Na przykład w mojej aplikacji są wykresy. Nie byłem w stanie dowiedzieć się, jak zautomatyzować testowanie wykresów. Potrzeba ludzkiego oka, AFAIK, aby sprawdzić, czy wykres jest poprawny.

(Używam Java Swing)

Steve McLeod
źródło
1
Jest świetny artykuł na temat różnych architektur GUI autorstwa Martina Fowlera ( martinfowler.com/eaaDev/uiArchs.html ). Opisuje kompromisy architektury GUI w zakresie testów jednostkowych.
Roman Hwang
1
W dzisiejszych czasach to pytanie byłoby lepiej zadane na programmers.stackexchange.com (i prawdopodobnie jest poza tematem na Stack Overflow, ponieważ jest zbyt szerokie), ale starych pytań nie można migrować. Odkładając na bok kwestię, czy należy to tutaj, problem pozostaje interesujący i trudny.
Mark Amery,
1
Byłoby wspaniale mieć przykład z fragmentem kodu GUI i JUnitem.
Witold Kaczurba
1
Powiedziałbym, po prostu zrelaksuj się i nie przejmuj się. Wysiłek włożony w testy jednostkowe nie zawsze okazuje się produktywny netto.
codeulike
Stare pytanie, możesz przetestować przepływ w GUI za pomocą Jubula
Abi

Odpowiedzi:

68

Projekty takie jak MVP i MVC zazwyczaj próbują wyodrębnić jak najwięcej logiki z rzeczywistego GUI. Bardzo popularnym artykułem na ten temat jest „The Humble Dialog Box” Michaela Feathersa. Osobiście miałem mieszane doświadczenia z próbami wyprowadzenia logiki z interfejsu użytkownika - czasami działało to bardzo dobrze, a innym razem sprawiało to więcej kłopotów, niż było warte. Jest to jednak trochę poza moim obszarem specjalizacji.

Jon Skeet
źródło
??? „Czasami działało to bardzo dobrze, a innym razem stanowiło więcej kłopotów niż było warte”. Bardzo dziwne, ponieważ większość nowych języków jest zorientowana na MVC ... co jest logiczne z gui (Model-Visual) ...
Patrick Desjardins
14
Mimo to logika prezentacji będzie w GUI. Czasami może to nie być trywialne
Andrea
16
Mirror: The Humble Dialog Box
c24w,
Martin Fowler potraktował tę koncepcję (w przypadku Twojej sieci, takiej jak moja, filtry archive.org): martinfowler.com/eaaDev/uiArchs.html#HumbleView
Christopher Berman
@ c24w dziękuję za wyciągnięcie tego lustra, jesteś prawdziwym MVP :)
John Baker
38

Oczywiście odpowiedzią jest użycie MVC i przeniesienie jak największej logiki z GUI.

To powiedziawszy, słyszałem od współpracownika dawno temu, że kiedy SGI przenosił OpenGL na nowy sprzęt, mieli kilka testów jednostkowych, które rysowały zestaw pierwotnych na ekranie, a następnie obliczały sumę MD5 bufora ramki. Wartość tę można następnie porównać ze znanymi dobrymi wartościami skrótu, aby szybko określić, czy interfejs API jest dokładny na piksel.

dicroce
źródło
3
Podoba mi się to podejście. Uciążliwe w konfiguracji i utrzymaniu, ale dałoby mi to możliwości testowania regresji, których potrzebuję.
Steve McLeod,
7
danatel przegapiłeś punkt. OpenGL to interfejs API do renderowania grafiki z dokładnością do pikseli. Struktury aplikacji GUI, takie jak Qt, będą w dużym stopniu zależne od karnacji systemowej, więc haszowanie bufora ramki nie jest dobrym podejściem.
Bob Somers
1
MD5? Co ma z tym wspólnego kryptograficzny hash? Jaki jest wpływ na bezpieczeństwo? Hasz, OK, to świetny pomysł na doskonałą grafikę w pikselach, ale hasz kryptograficzny? Możesz używać szybszych skrótów, które nie są kryptograficzne i których prawdopodobieństwo kolizji jest znikome. Czy na pewno był to skrót kryptograficzny, a nie zwykły skrót? (ponadto, w dzisiejszych czasach obliczeń równoległych, algorytm haszujący [używany do celów
niekryptograficznych
24
@ SyntaxT3rr0r: Jaką funkcję skrótu poleciłbyś w tego typu aplikacjach niezwiązanych z bezpieczeństwem i jakiego poziomu wzrostu wydajności można się spodziewać w porównaniu z MD5?
Lèse majesté
1
Odpowiedź oznacza „nigdy nie projektuj swojego GUI i dlatego nie testuj go”. Chłodny.
Przyciemnia
10

Możesz wypróbować UISpec4J to funkcjonalna i / lub biblioteka testów jednostkowych Open Source dla aplikacji Java opartych na Swing ...

CMS
źródło
2
Zacząłem używać UISpec4J przez mniej więcej miesiąc do testowania walidacji wymagań na GUI Java Swing. Do tej pory bardzo mi się to podobało.
Bassam
github.com/UISpec4J/UISpec4J stwierdza, że ​​Twój link jest oficjalną stroną internetową, ale dla mnie nie wygląda tak oficjalnie. Widzę tylko blog o vlogowaniu
lucidbrot,
7

Jest Selenium RC , które zautomatyzuje testowanie interfejsu użytkownika opartego na sieci. Będzie rejestrować działania i odtwarzać je. Nadal będziesz musiał przejść przez interakcje z interfejsem użytkownika, więc nie pomoże to w pokryciu, ale może być używane do automatycznych kompilacji.

David Robbins
źródło
7

Możesz spróbować użyć Cucumber and Swinger do pisania funkcjonalnych testów akceptacyjnych w prostym języku angielskim dla aplikacji Swing GUI. Swinger korzysta z biblioteki Jemmy Netbeans pod maską do obsługi aplikacji.

Ogórek pozwala pisać testy takie jak ten:

 Scenario: Dialog manipulation
    Given the frame "SwingSet" is visible
    When I click the menu "File/About"
    Then I should see the dialog "About Swing!"
    When I click the button "OK"
    Then I should not see the dialog "About Swing!"

Obejrzyj demo wideo Swinger, aby zobaczyć, jak działa.

Dema
źródło
6

Oto kilka wskazówek:

Spróbuj usunąć jak najwięcej kodu z GUI (mieć kontroler i obiekt modelu) w ten sposób będziesz mógł je przetestować bez GUI.

W przypadku grafiki należy przetestować wartość, którą podajesz do kodu generującego grafikę.

Patrick Desjardins
źródło
6

Testowanie to forma sztuki. Zgadzam się, że logika powinna zostać usunięta z GUI tak bardzo, jak to możliwe. Wtedy możemy skupić się na naszych testach jednostkowych. Jak wszystko inne testowanie polega na zmniejszaniu ryzyka. Nie zawsze musisz wszystko testować, ale często najlepiej jest przerwać różne testy w różnych obszarach.

Drugie pytanie dotyczy tego, co tak naprawdę próbujesz przetestować w warstwie interfejsu użytkownika. Testowanie interfejsu użytkownika jest najdroższym testem, ponieważ zwykle trwa dłużej, aby go utworzyć, utrzymać i jest najbardziej kruchy. Jeśli przetestujesz logikę, aby wiedzieć, że współrzędne są poprawne, zanim spróbujesz narysować linię, co dokładnie testujesz? Jeśli chcesz przetestować wykres z czerwoną linią, rysuje się. Czy możesz podać mu ustalone z góry współrzędne i sprawdzić, czy określone piksele są czerwone, czy nie? Jak zasugerowano powyżej, porównania bitmap działają, Selenium, ale moim głównym celem nie byłoby przesadne testowanie GUI, ale raczej przetestowanie logiki, która pomoże stworzyć interfejs użytkownika, a następnie skup się na tym, która część interfejsu użytkownika psuje się lub jest podejrzana i skupi się na kilku testach tam.

Charles Smith
źródło
3

Możesz użyć JFCUnit do przetestowania swojego GUI, ale grafika może być trudniejsza. Kilka razy zrobiłem migawki mojego GUI i automatycznie porównałem go z poprzednią wersją. Chociaż nie zapewnia to rzeczywistego testu, ostrzega, jeśli automatyczna kompilacja nie przyniesie oczekiwanych wyników.

Steve Moyer
źródło
3

Z twojego pytania wyciągam wniosek, że szukasz zautomatyzowanego sposobu szczegółowego przetestowania zachowania GUI, podany przykład to sprawdzenie, czy krzywa jest rzeczywiście narysowana poprawnie.

Struktury testów jednostkowych umożliwiają przeprowadzanie testów automatycznych, ale myślę, że rodzaj testów, które chcesz wykonać, to skomplikowane testy integracyjne, które weryfikują prawidłowe zachowanie wielu klas, w tym klas z zestawu narzędzi / biblioteki GUI, nie powinien chcieć testować.

Twoje opcje zależą w dużej mierze od używanych platform / zestawów narzędzi / frameworków: na przykład aplikacja używająca Qt jako struktury GUI może używać Squish do automatyzacji swoich testów. Weryfikujesz wyniki swoich testów raz, a kolejne automatycznie wykonywane testy porównują wyniki z wynikami zweryfikowanymi.

andreas buykx
źródło
2

Okno Licker dla Swing & Ajax

robi-y
źródło
2

Moje podejście do testowania GUI ewoluuje, podobnie jak konsensus branżowy. Myślę jednak, że zaczyna się pojawiać kilka kluczowych technik.

Używam jednej lub więcej z tych technik, w zależności od sytuacji (np. Jaki to rodzaj GUI, jak szybko należy go zbudować, kim będzie użytkownik końcowy itp.).

  1. Testowanie ręczne. Zawsze masz uruchomiony GUI podczas pracy nad kodem i upewnij się, że jest zsynchronizowany z kodem. Ręcznie testujesz i ponownie testujesz część, nad którą pracujesz, podczas pracy nad nią, przełączając się między kodem a uruchomioną aplikacją. Za każdym razem, gdy wykonujesz jakąś znaczącą pracę, poddajesz cały ekran lub obszar aplikacji całościowy test, aby upewnić się, że nie ma regresji.

  2. Testów jednostkowych. Piszesz testy dla funkcji lub małych jednostek zachowania GUI. Na przykład wykresy mogą wymagać obliczenia różnych odcieni koloru w oparciu o kolor „bazowy”. Możesz wyodrębnić to obliczenie do funkcji i napisać dla niej test jednostkowy. Możesz wyszukać logikę taką jak ta w GUI (zwłaszcza logikę wielokrotnego użytku) i wyodrębnić ją do dyskretnych funkcji, które można łatwiej przetestować jednostkowo. W ten sposób można wyodrębnić i przetestować nawet złożone zachowanie - na przykład sekwencję kroków w kreatorze można wyodrębnić do funkcji, a test jednostkowy może zweryfikować, czy po wprowadzeniu danych wejściowych zwracany jest prawidłowy krok.

  3. Eksplorator komponentów. Tworzysz ekran „eksploratora”, którego jedyną rolą jest pokazanie każdego z komponentów wielokrotnego użytku, które tworzą twój GUI. Ten ekran umożliwia szybkie i łatwe wizualne sprawdzenie, czy każdy element ma właściwy wygląd i styl. Eksplorator komponentów jest bardziej wydajny niż ręczne przeglądanie całej aplikacji, ponieważ A) musisz zweryfikować każdy komponent tylko raz i B) nie musisz wchodzić w głąb aplikacji, aby zobaczyć komponent, możesz po prostu wyświetlić i sprawdź to natychmiast.

  4. Testowanie automatyczne. Piszesz test, który współdziała z ekranem lub komponentem, symulując kliknięcia myszą, wprowadzanie danych itp., Zapewniając, że aplikacja działa poprawnie przy tych manipulacjach. Może to być przydatne jako dodatkowy test zapasowy, aby wychwycić potencjalne błędy, które mogą zostać pominięte w innych testach. Zwykle rezerwuję testowanie automatyzacji dla tych części GUI, które są najbardziej podatne na uszkodzenia i / lub są bardzo krytyczne. Części, w przypadku których chcę jak najwcześniej wiedzieć, czy coś się zepsuło. Może to obejmować bardzo złożone komponenty interaktywne, które są podatne na uszkodzenia lub ważne ekrany główne.

  5. Testowanie różnic / migawek. Piszesz test, który po prostu przechwytuje dane wyjściowe jako zrzut ekranu lub jako kod HTML i porównuje je z poprzednim wynikiem. W ten sposób jesteś powiadamiany o każdej zmianie wyniku. Testy różnicowe mogą być przydatne, jeśli wizualny aspekt GUI jest złożony i / lub podlega zmianom. W takim przypadku potrzebujesz szybkiej i wizualnej informacji zwrotnej na temat wpływu danej zmiany na GUI jako całość.

Zamiast ciężko używać każdego możliwego rodzaju testu, wolę wybierać technikę testowania w oparciu o rodzaj rzeczy, nad którą pracuję. Więc w jednym przypadku wyodrębnię prostą funkcję i przetestuję ją jednostkowo, ale w innym przypadku dodam komponent do eksploratora komponentów itd. To zależy od sytuacji.

Nie znalazłem pokrycia kodu jako bardzo użytecznego wskaźnika, ale inni mogli znaleźć dla niego zastosowanie.

Myślę, że pierwszą miarą jest liczba i powaga błędów. Twoim głównym priorytetem jest prawdopodobnie posiadanie aplikacji, która działa poprawnie. Jeśli aplikacja działa poprawnie, powinno być niewiele lub żadnych błędów. Jeśli jest wiele lub poważnych błędów, przypuszczalnie albo nie testujesz, albo twoje testy nie są skuteczne.

Oprócz ograniczania błędów istnieją inne środki, takie jak wydajność, użyteczność, dostępność, łatwość konserwacji, rozszerzalność itp. Będą się one różnić w zależności od rodzaju aplikacji, którą tworzysz, firmy, użytkownika końcowego itp.

Wszystko to jest oparte na moim osobistym doświadczeniu i badaniach, a także świetnym artykule na temat testów interfejsu użytkownika autorstwa Ham Vocke .

Jonathan
źródło
1

Z tego co wiem, jest to dość skomplikowane i naprawdę zależy od języka - wiele języków ma swój własny sposób testowania GUI, ale jeśli naprawdę potrzebujesz przetestować GUI (w przeciwieństwie do interakcji model / gui), często musisz symulować klikanie przycisków przez rzeczywistego użytkownika. Na przykład framework SWT używany w Eclipse zapewnia SWTBot , o JFCUnit już wspomniano, Mozilla ma swój własny sposób na symulowanie tego w XUL (iz tego, co czytałem na ich blogach, testy te wydają się dość kruche).

Czasami musisz zrobić zrzut ekranu i przetestować renderowanie w pikselach (uważam, że Mozilla robi to, aby sprawdzić poprawnie renderowane strony) - wymaga to dłuższej konfiguracji, ale może być tym, czego potrzebujesz do wykresów. W ten sposób, gdy aktualizujesz kod i test się kończy, musisz ręcznie sprawdzić obraz, czy błąd był prawdziwy, lub ulepszyłeś kod renderujący wykres, aby generował ładniejsze wykresy i musisz zaktualizować zrzuty ekranu.

Kim Sullivan
źródło
0

Jeśli używasz Swing, FEST-Swing jest przydatny do sterowania GUI i testowania asercji. Ułatwia to testowanie takich rzeczy, jak „jeśli kliknę przycisk A, powinno zostać wyświetlone okno dialogowe B” lub „jeśli wybiorę opcję 2 z listy rozwijanej, wszystkie pola wyboru powinny zostać odznaczone” .

Scenariusz wykresu, o którym wspomniałeś, nie jest łatwy do przetestowania. Całkiem łatwo jest uzyskać pokrycie kodu dla komponentów GUI, po prostu tworząc je i wyświetlając (i być może sterując nimi za pomocą FEST). Jednak tworzenie znaczących stwierdzeń jest trudną częścią (a pokrycie kodu bez znaczących twierdzeń jest ćwiczeniem w oszukiwaniu samego siebie). Jak sprawdzić, czy wykres nie był odwrócony do góry nogami lub zbyt mały?

Myślę, że musisz po prostu zaakceptować, że niektórych aspektów GUI nie można skutecznie przetestować za pomocą automatycznych testów jednostkowych i że będziesz musiał przetestować je w inny sposób.

Dan Dyer
źródło
0

Twoim zadaniem nie jest testowanie biblioteki GUI. Możesz więc uniknąć odpowiedzialności za sprawdzenie, co jest faktycznie narysowane na ekranie, i zamiast tego sprawdzić właściwości widżetów, ufając bibliotece, że dokładnie reprezentują to, co jest rysowane.

ivan_pozdeev
źródło