Jestem całkiem nowy w świecie testów jednostkowych i właśnie postanowiłem w tym tygodniu dodać zasięg testowy do mojej istniejącej aplikacji.
To ogromne zadanie, głównie ze względu na liczbę klas do przetestowania, ale także dlatego, że pisanie testów jest dla mnie zupełnie nowe.
Pisałem już testy dla wielu klas, ale teraz zastanawiam się, czy robię to dobrze.
Kiedy piszę testy dla metody, mam wrażenie, że przepisuję po raz drugi to, co już napisałem w samej metodzie.
Moje testy wydają się tak ściśle związane z metodą (testowanie całej ścieżki kodowej, spodziewając się, że niektóre wewnętrzne metody będą wywoływane kilka razy, z pewnymi argumentami), że wydaje się, że jeśli kiedykolwiek zmienię metodę, testy nie powiodą się, nawet jeśli ostateczne zachowanie metody nie uległo zmianie.
To tylko uczucie i, jak powiedziano wcześniej, nie mam doświadczenia w testowaniu. Gdyby niektórzy bardziej doświadczeni testerzy mogli udzielić mi porady, jak napisać świetne testy dla istniejącej aplikacji, byłoby to bardzo mile widziane.
Edycja: Chciałbym podziękować przepełnieniu stosu, miałem świetne dane wejściowe w mniej niż 15 minut, które odpowiadały więcej godzinom czytania online, które właśnie zrobiłem.
źródło
Odpowiedzi:
Myślę, że robisz to źle.
Test jednostkowy powinien:
Nie powinien zaglądać do metody, aby zobaczyć, co robi, więc zmiana elementów wewnętrznych nie powinna spowodować niepowodzenia testu. Nie powinieneś bezpośrednio sprawdzać, czy wywoływane są metody prywatne. Jeśli chcesz dowiedzieć się, czy Twój prywatny kod jest testowany, skorzystaj z narzędzia do pokrycia kodu. Ale nie przejmuj się tym: 100% ubezpieczenia nie jest wymagane.
Jeśli twoja metoda wywołuje metody publiczne w innych klasach, a wywołania te są gwarantowane przez interfejs, możesz przetestować, czy te wywołania są wykonywane przy użyciu frameworku.
Nie należy używać samej metody (ani żadnego używanego przez nią kodu wewnętrznego) do dynamicznego generowania oczekiwanego wyniku. Oczekiwany wynik powinien być zakodowany na stałe w twoim przypadku testowym, aby nie zmieniał się, gdy zmienia się implementacja. Oto uproszczony przykład tego, co powinien zrobić test jednostkowy:
Zauważ, że sposób obliczania wyniku nie jest sprawdzany - tylko że wynik jest poprawny. Dodawaj coraz więcej prostych przypadków testowych, takich jak powyższe, aż obejmiesz jak najwięcej scenariuszy. Skorzystaj z narzędzia do pokrywania kodu, aby sprawdzić, czy przegapiłeś jakieś interesujące ścieżki.
źródło
Do testów jednostkowych uznałem, że zarówno Test Driven (najpierw testy, drugi kod), jak i pierwszy kod, drugi test, są niezwykle przydatne.
Zamiast pisać kod, a następnie pisać test. Napisz kod, a następnie spójrz na to, co MYŚLISZ, że kod powinien robić. Pomyśl o wszystkich zamierzonych zastosowaniach, a następnie napisz test dla każdego. Testy pisania są szybsze, ale bardziej zaangażowane niż samo kodowanie. Testy powinny przetestować intencję. Pomyśl także o zamiarach znalezienia narożnych skrzynek w fazie pisania testu. I oczywiście podczas pisania testów może się zdarzyć, że jedno z niewielu zastosowań powoduje błąd (coś, co często znajduję i jestem bardzo zadowolony, że ten błąd nie uszkodził danych i nie został sprawdzony).
Jednak testowanie przypomina prawie dwukrotne kodowanie. W rzeczywistości miałem aplikacje, w których było więcej kodu testowego (ilości) niż kod aplikacji. Jednym z przykładów była bardzo złożona maszyna stanu. Musiałem się upewnić, że po dodaniu do niego większej logiki, wszystko zawsze działało na wszystkich poprzednich przypadkach użycia. A ponieważ te przypadki były dość trudne do prześledzenia, patrząc na kod, skończyło się na tak dobrym pakiecie testowym dla tej maszyny, że byłem pewien, że nawet się nie złamie po wprowadzeniu zmian, a testy uratowały mi tyłek kilka razy . A ponieważ użytkownicy lub testerzy znaleźli błędy w przepływach lub przypadkach narożnych, które nie zostały uwzględnione, zgadnij, co dodało do testów i nigdy więcej się nie powtórzyło. To naprawdę dało użytkownikom pewność co do mojej pracy i uczyniło całość super stabilną. A kiedy trzeba go było przepisać ze względu na wydajność, zgadnij co,
Wszystkie proste przykłady, takie jak,
function square(number)
są świetne i są prawdopodobnie złymi kandydatami do spędzania dużo czasu na testowaniu. Te, które wykonują ważną logikę biznesową, czyli tam, gdzie ważne jest testowanie. Przetestuj wymagania. Nie tylko testuj hydraulikę. Jeśli wymagania się zmienią, zgadnij co, testy też muszą.Testowanie nie powinno dosłownie testować tej funkcji trzy razy przywołany pasek funkcji foo. To jest złe. Sprawdź, czy wynik i skutki uboczne są prawidłowe, a nie mechanika wewnętrzna.
źródło
Warto zauważyć, że modyfikowanie testów jednostkowych w istniejącym kodzie jest znacznie trudniejsze niż kierowanie tworzeniem tego kodu za pomocą testów. To jedno z głównych pytań dotyczących starszych aplikacji ... jak przeprowadzić test jednostkowy? Ten został poproszony wiele razy wcześniej (więc może być zamknięty jako pytanie dupe), a ludzie zazwyczaj kończy się tutaj:
Przeniesienie istniejącego kodu do Test Driven Development
Popieram zalecenie książki przyjętej odpowiedzi, ale poza tym w odpowiedziach znajduje się więcej informacji.
źródło
Nie pisz testów, aby uzyskać pełne pokrycie kodu. Napisz testy, które gwarantują twoje wymagania. Możesz odkryć niepotrzebne ścieżki kodowe. I odwrotnie, jeśli są konieczne, muszą spełnić pewien wymóg; znajdź to, co to jest i przetestuj wymaganie (nie ścieżkę).
Utrzymuj małe testy: jeden test na każde wymaganie.
Później, gdy musisz wprowadzić zmiany (lub napisać nowy kod), spróbuj najpierw napisać jeden test. Tylko jeden. Następnie zrobisz pierwszy krok w rozwoju opartym na testach.
źródło
Testy jednostkowe dotyczą wyników uzyskanych z funkcji / metody / aplikacji. Nie ma znaczenia, w jaki sposób powstaje wynik, liczy się tylko to, że jest poprawny. Dlatego twoje podejście do liczenia wywołań metod wewnętrznych i takie jest błędne. To, co zwykle robię, to usiąść i napisać, co metoda powinna zwrócić, biorąc pod uwagę określone wartości wejściowe lub określone środowisko, a następnie napisać test, który porównuje rzeczywistą wartość zwróconą z tym, co wymyśliłem.
źródło
Spróbuj napisać test jednostkowy przed napisaniem metody, którą zamierza przetestować.
To z pewnością zmusi cię do nieco innego myślenia o tym, jak się to robi. Nie będziesz miał pojęcia, jak ta metoda zadziała, tylko co ma zrobić.
Zawsze powinieneś testować wyniki metody, a nie to, w jaki sposób metoda uzyskuje te wyniki.
źródło
testy mają poprawić łatwość konserwacji. Jeśli zmienisz metodę, a test się zepsuje, może to być dobra rzecz. Z drugiej strony, jeśli spojrzysz na swoją metodę jako czarną skrzynkę, to nie powinno mieć znaczenia, co jest w środku metody. Faktem jest, że musisz kpić z niektórych testów, aw takich przypadkach naprawdę nie możesz traktować tej metody jako czarnej skrzynki. Jedyne, co możesz zrobić, to napisać test integracyjny - ładujesz w pełni utworzoną instancję testowanej usługi i każesz jej działać tak, jakby działała w Twojej aplikacji. Następnie możesz potraktować to jak czarne pudełko.
Wynika to z faktu, że piszesz testy po napisaniu kodu. Jeśli zrobiłeś to na odwrót (najpierw napisałeś testy), nie czułbyś się w ten sposób.
źródło