Professional Documents
Culture Documents
reserved.
Marcin Kośka/Woblink
Konsultacja merytoryczna
identyfikacji.
Copyright © for the Polish edition by Wydawnictwo Naukowe PWN SA
Warszawa 2019
ISBN 978-83-01-20854-7
(wyd. I)
Warszawa 2019
infolinia 801 33 33 88
www.pwn.pl
Spis treści
O autorze
O recenzencie technicznym
Podziękowania
Wprowadzenie
Refaktoryzacja
Ciągłe doskonalenie
Testowanie eksploracyjne
Różnorodność narzędzi
Klasyfikacja narzędzi
dostarczania
Odwracanie koła
Najprostsze podejście
Testowanie nocne
krytycznych
Ciągła integracja
Wydania kanarkowe
Podsumowanie
Omówienie warstw
Rzeczywista architektura
Architektura planowana kontra architektura rzeczywista
Typowe warianty
Łączenie testów
Podsumowanie czynników
Stan
czasie
Techniki izolacji
Podsumowanie
Prawo Conwaya
z automatyzacją testów
Podsumowanie
Omówienie procesu
Proces
Podsumowanie
Podsumowanie
Tworzenie projektu
Pisanie pseudokodu
Podsumowanie
zaimplementowania
Uruchamianie IISExpress
Kończenie testu
Podsumowanie
Unikanie debugowania
Rozwiązywanie problemu
Więcej problemów…
Przechwytywanie ekranu
Rejestrowanie
Rejestrowanie zagnieżdżone
Rejestrowanie wizualne
MVCForum
Podsumowanie
Oczyszczanie
Poprawienie wydajności
Podsumowanie
Ulepszanie izolacji
Podsumowanie
akceptacyjnymi (ATDD)
Dług techniczny
Proces
szczegółów i czytelnością
testami (TDD)
Czerwone-zielone-refaktoryzacja
Podsumowanie
Testy wydajności
i testami wydajności
Badanie wąskich gardeł w wydajności
Testy obciążeniowe
Testowanie wdrożenia
Testowanie wizualne
platformach
Testy instalacji
instalacji dyskretnej
Testy aktualizacji
inteligencji
Podsumowanie
Rozdział 19. Co dalej?
Popełniaj błędy
Rozwiązanie
Izolowanie środowisk
Opis architektury
Wdrożenie minimalne
Struktura organizacyjna
Testy kompleksowe
DODATEK B. Mechanizm oczyszczania
Problem
Proste rozwiązanie
Podsumowanie
Kontekst
Struktura projektu
Pakiety NuGet
Funkcje i narzędzia
TestAutomationEssentials.Common
TestAutomationEssentials.MSTest
TestAutomationEssentials.CodedUI
TestAutomationEssentials.Selenium
programisty
Poka-Yoke
programowania.
automatyzacji testów.
a wiem, że nie było to proste! Choć robiłem co w mojej mocy, aby praca
od pisania tej książki, ale jak widać to mu się udało. Miałeś rację
wydawnictwa Apress.
nad tą książką.
Wam wszystkim!
Wprowadzenie
z tych książek nie jest uniwersalna. Jak to ktoś kiedyś powiedział: „Te
swobodne nurkowanie…”.
zbyt nieaktualne. Choć ogólnie zgadzam się z tym, że idea, zgodnie z którą
staramy się omówić prawie każdy aspekt automatyzacji testów, jest ona
części napisany został w języku C#, ale same koncepcje i pojęcia można
Gdy po raz pierwszy usiadłem do pisania tej książki, starałem się myśleć
tak więc napisałem „gruntowny spis” tematów, które chciałem w tej książce
omówić i po prostu zacząłem je pisać, przelewając swoją wiedzę
temat metodyki Agile), ogólna struktura tej książki zaczęła się stopniowo
odpowiada bardziej na ogólne pytania typu „dlaczego” oraz „co”, zaś druga
pozostałe. Można przy tym też skakać w przód i w tył do innych rozdziałów
wyzwaniom.
i chcą się dowiedzieć, jak wpasowuje się ona w szeroki obraz tworzenia
pomogą nam również zrozumieć to, czego możemy, a także czego nie
decyzji, jakie nas czekają (czego wiele osób nie bierze nawet pod uwagę!)
i pokaże nam, jaki wpływ może mieć każda z nich. Nawet jeśli nie jesteśmy
je naszym menedżerom.
część pomoże nam poszerzyć w tym temacie nasze horyzonty i pokaże nam
tworzenia oprogramowania.
dwie grupy (przy czym podział ten nie jest nigdzie jawnie podany,
maksimum korzyści.
projekcie.
Część I:
Rozdział 1: Wartość automatyzacji testów – w tym rozdziale
wybranej opcji.
kultury biznesu.
Część II:
samouczka.
automatycznych.
pracy.
niepowodzenia w przyszłości.
więcej.
metodykę Agile.
automatyzacji testów.
dodatki:
Przyjemnej lektury!
Część I. „Dlaczego” oraz „co”
Ponieważ książka ta nosi tytuł Automatyzacja testów. Kompletny
Przyjemnej lektury!
Rozdział 1. Wartość automatyzacji
testów
temat, starając się w ten sposób wyjaśnić, czym tak naprawdę jest
skrócenia czasu trwania cyklu testowego stał się w ostatnich latach tak
istotny.
latach. Jest wiele powodów, dla których tak się stało, ale bez wątpienia
sprawdzenia. Jeśli każdy test wykonywany jest tylko raz lub dwa razy, to
niż je automatyzować.
razy na minutę!
Kent Beck
James Grenning
Robert C. Martin
Mike Beedle
Jim Highsmith
Steve Mellor
Andrew Hunt
Ken Schwaber
Alistair Cockburn
Ron Jeffries
Jeff Sutherland
Ward Cunningham
Jon Kern
Dave Thomas
Martin Fowler
Brian Marick
testów stała się tak istotna. Nie jest to jednak jedyny ważny powód.
complexity).
sobą pewien koszt. Koszt ten jest oczywiście częścią całkowitego kosztu
co naturalnie zwiększa jego koszt. Istnieją jednak dwa czynniki, które mogą
mały lub zerowy wpływ na złożoność funkcji już istniejących. Oznacza to,
kolejnych funkcji złożoność rośnie dużo szybciej niż liniowo (patrz rysunek
1.3). To z kolei powoduje również wzrost kosztów dodawania nowych
czasu
liniowy
Rysunek 1.3. Powszechny przypadek: złożoność rośnie dużo szybciej
z upływem czasu
W większości przypadków przerywanie dotychczasowych prac
(tworzonej od zera) wersji z wersją poprzednią, będzie już ona miała swoją
Refaktoryzacja
musimy bardzo często go testować. Jest to drugi ważny powód, dla którego
kontrolą.
Ciągłe doskonalenie
do zmiany.
Rysunek 1.6. Automatyzacja testów powiązana jest z wieloma innymi
danych wyświetlanych na ekranie, które nie są istotne dla testu itd. Niektóre
nam się rozwiązać przy użyciu narzędzi, to nadal istnieć będzie duża wada
niepowodzeń.
regresji, aby upewnić się, że wszystko działa dokładnie tak jak do tej
pory!”. Pozwólcie, że odpowiem w ten sposób: jeśli nikt nie ruszał kodu6
żaden programista nie będzie raczej zmieniał kodu, jeśli nie zamierza on
aplikacji, nawet jeśli nie pasują już do siebie dokładnie. Ten osąd i zdrowy
równi.
problemy:
Oczywiście może się zdarzyć, że błąd pojawi się już przy pierwszym
Nawet jeśli wpływ tej zmiany jest bardzo mały dla człowieka, powoduje
nakreślany tu przeze mnie obraz może być wykonalny dla kilku zespołów,
no nie, musimy przecież mieć oczy otwarte, aby móc czytać dalej…
Jeśli testy wykonują się tak szybko, możemy sprawić, że będą się one
każdego programisty (co też może być wykonywane bardzo często) i będą
błędów regresji! Tak więc, jeśli już na samym początku nie mieliśmy
swój kod i nadal mieć pewność, że niczego w ten sposób nie popsują
razem, gdy opracowywana jest jakaś nowa funkcja, wraz z nią tworzone są
HISTORYJKI UŻYTKOWNIKA
użytkownika.
problemu.
Jako <rola>
Aby móc <cel>
Na przykład:
dwa typy:
testowanie eksploracyjne,
testowanie zaplanowane.
i czy w ogóle tworzy i planuje testy. Niektóre zespoły skupiają się głównie
Testowanie eksploracyjne
testowania jest przydatny, gdy naszym celem jest znalezienie tak dużej
nawet gdy realizuje zaplanowany test, nie tylko ma zupełną swobodę, ale
błędy, test powinien wiedzieć, czego należy się spodziewać, a czego nie.
O ile tester manualny posiada taką intuicyjną wiedzę, to maszyna już nie.
automatycznego nie jest znalezienie tak dużej liczby błędów, jak to tylko
możliwe, ale raczej dostarczenie szybkiej informacji zwrotnej o tym, czy
w testach.
pewnych nietrywialnych reguł, wówczas test taki bardzo szybko stanie się
stosować proste testy, które weryfikują tylko jeden lub kilka konkretnych
również wykracza poza zakres tej książki. Tak więc od tej pory, jeśli nie
EKSPLORACYJNE
rozumienia ich kontekstu) – jak mogą to robić małpy lub małe dzieci –
w celu sprawdzenia, czy dany program ulegnie awarii, czy też nie.
każdej akcji. Nawet jeśli program zawiesi się (ale nie ulegnie
w sensowny sposób.
nie wciśnie losowo klawisza „Enter” lub „Esc” bądź też nie kliknie
Teraz, gdy rozumiemy już, że testy automatyczne nie nadają się zbytnio do
Dokładność
a przy tym mają takie same założenia dotyczące systemu i sposobu jego
Łatwość utrzymania
kodu, który nie uległ żadnej zmianie, więc należy zawsze oczekiwać, że
automatyzacji testów liczy się każdy mały szczegół. Z tego powodu testy
narzędzi zamiast do elementu menu, nawet jeśli sam opis tego kroku się nie
się niepowodzeniem.
z nich.
Na szczęście dokładność nie oznacza koniecznie zaśmiecania każdego
czymś więcej niż tylko zwykłą kolekcją skryptów testowych, ale może –
fragmentów.
rysunek, który daje nam „pełny obraz” samochodu, ale z dużo mniejszą
nie powinny one znajdować się w tym samym miejscu, ale należy je
Obsługa niepowodzeń
Przy pierwszym wykonaniu zaplanowanego przypadku testowego możemy
świadomi.
pamięci itd.
5. Ktoś zrobił coś z systemem przed lub w czasie trwania testu, co w sposób
szczegółowo.
Ważna uwaga
w rozdziałach 6 i 7.
POWTARZAĆ?
niepomyślnie dopiero wtedy, gdy żadna z tych prób nie zakończyła się
sukcesem. Jednak według mnie popełniają oni w ten sposób błąd.
Każde niepowodzenie testu daje nam jasny sygnał: albo mamy jakiś
podejmuje ona decyzje, czy należy kontynuować test, cofnąć się o kilka
tylko pogorszymy tę sprawę, ponieważ nasz kod testu będzie miał teraz
teście zazwyczaj przerywa ten test i uruchamia kolejny, nie chcemy, aby
zdaniem mogą być istotne. Podczas pisania takiego raportu osoba testująca
ciągłej integracji), lub wykonać jego kroki ręcznie i w ten sposób zbadać
dla testu, jak i aplikacji – jak również dowolnymi innymi dowodami, które
mogą pomóc zbadać dany problem. Dowodem takim może być zrzut lub
w rozdziałach 5 i 15.
Zaufanie
prawdziwych błędów.
łagodniejszą wersję:
przyczynę)
zaprojektowane.
fałszywe, objawia się wtedy, gdy istnieje wiele testów, które przez długi
w rozdziale 13).
testów. Oczywiście jest jeszcze Selenium, tak więc jest ich bazylion i jeden.
narzędzia realizują więcej niż jeden cel, przy czym w większości wypadków
dowiedzieć się, które z tych narzędzi będą dla nas najbardziej odpowiednie,
powinniśmy najpierw odpowiedzieć sobie na kilka pytań. O ile pytanie
pomijane. Pytanie to nie jest pytaniem typu „dlaczego”, „co” ani też „jak”,
ma swoje własne wady i zalety, będziemy zatem sami musieli podjąć taką
jesteśmy, dzięki czemu łatwiej nam będzie się z nimi zmierzyć. Na dłuższą
metę możemy nawet sami rozważyć lub przynajmniej spróbować nakłonić
Udają się więc do swojego szefa i mówią mu, że mogą szybko zacząć
i cieszą się na myśl o pisaniu kodu. Takie osoby często postrzegane są jako
Przydzielenie tego zadania komuś, kogo już znamy i komu ufamy, a kto
jedynie od 20% do 50% czasu swojej pracy, natomiast przez resztę czasu
testów, gdy zespół taki zostanie już odpowiednio utworzony, o tyle zwykle
Takie testy zwykle będą kończyć się sukcesem i mogą nawet znaleźć jakieś
interesujące błędy.
poradzić. Ale gdy liczba testów zacznie się zwiększać, wtedy bez
właściwego planowania i projektowania, oraz bez odpowiednich
coś, co może mieć wpływ na dużą liczbę testów. Naprawa tego zajmie sporo
czasu, tak więc bez względu na to, czy sama aplikacja działa poprawnie czy
automatyzację, a które nie. Z jednej strony przez cały czas dokonują oni
sytuacja, w której jeden lub więcej testów kończy się niepowodzeniem bez
sukcesem. Hura! Wkrótce jednak, nie licząc już tego, że testy stałyby się
tylko częściowo (np. 20–50% swojego czasu pracy), a przez resztę czasu
problemów.
jedną czynność, a reszty czasu na inną, prawie nigdy nie jest dobrym
w tym samym biurze z osobami, które oczekują naszej pomocy przy jakichś
innych działaniach. Jeśli nasz menedżer lub my sami nie wyznaczymy sobie
konkretnych dni lub liczby godzin na realizację tego zadania, trudno nam
zawsze będą mieć wyższy priorytet. Poza tym samo pisanie testów
testy każdej nocy, to ich wyniki trzeba będzie sprawdzać każdego ranka!
przez co trudniej nam będzie dowiedzieć się, dlaczego coś się popsuło. Gdy
będziemy w stanie stwierdzić, czy nasze zmiany były prawidłowe – ale czy
wyników automatyzacji, czy nie, tak więc ich nie oczekują, a tym samym
nie przykładają do nich zbyt dużej wagi. W rezultacie ludzie ci widzą, że nie
zaufanie.
Wniosek
potrzebny jest czas, wysiłek i poświęcenie, tak więc nie jest to coś,
programistą na świecie.
zwykle wskazuje, ile pracy można wykonać bez pisania kodu, a ile będzie
wymagać kodowania.
zrobić coś, do czego nie były one projektowane. Zwykle są one dostarczane
KDT). W ramach tego podejścia skrypty testowe składają się wyłącznie (lub
dowiedzieć, co taki skrypt robi, bez wdawania się przy tym w jakiekolwiek
narzędzia dostępne w czasie, gdy rozpoczynali nad nimi prace, nie były dla
i utrzymywania testów.
W takich sytuacjach kolejnym częstym problemem jest to, że w celu
taki projektuje się zbyt ogólnie. Objawia się to tym, że element taki
przyjmuje zbyt dużą lub zbyt małą liczbę parametrów, których wartości
błędy, zaś osoba pisząca skrypt powinna znać dokładny format danych
sobie o nich więcej w dalszej części tego rozdziału). Kategoria ta różni się
z tych narzędzi jest typu open source), wiele zespołów używa ich do
czytelności, i odwrotnie.
czasu.
Dużą zaletą takiego zespołu jest to, że jego członkowie dzielą się między
znaleźć w rozdziałach 6 i 8.
Z drugiej strony, ponieważ taki zespół jest bardzo zwarty, zwykle nie
z konsekwencji tej sytuacji jest to, że zespół taki zwykle pisze testy
1. Jeśli testowany kod nie był pisany pod kątem testowania, jego
a sami deweloperzy zwykle nie będą się tym przejmować, dopóki nie
w rozdziale 5.
mieli możliwość dzielenia się ze sobą wiedzą, kodem i pomysłami, zaś jeden
deweloperów automatyzacji
w rozdziale 4.
testowania aplikacji.
(patrz rozdział 17), ale nie ma żadnego powodu, aby nie mogli oni tego robić
zakresie11.
Różnorodność narzędzi
Jak już wspomnieliśmy wcześniej, wyboru odpowiedniego narzędzia należy
Klasyfikacja narzędzi
oparte na doświadczeniu i wiedzy autora tej książki, tak więc nie są one
pisanie kodu, czy też skorzystamy z jakiegoś narzędzia, które jest bardziej
takie jak Selenium, są albo obsługiwane przez wiele różnych języków, albo
czynniki:
nie tylko jest to najprostszy sposób, ale też testy jednostkowe pisane są
pozostać już przy tej decyzji i stosować różne obejścia, aby zintegrować
praktycznie niemożliwa!
funkcji.
wywołań zwrotnych już nie, tak naprawdę oferują one mniej więcej
takie same korzyści. Krótko mówiąc, umożliwiają one zmiennym
języków.
uruchomić – wszystkie lub tylko wybrane testy, lub też wyłącznie testy,
zależnych testów.
i MSTest, NUnit i xUnit dla .NET. Dla języka Python mamy wbudowane
języka, albo też darmowymi projektami open source. Tym samym ich cena
Uwaga
Biblioteki testowania nazywane są czasem jarzmem testowym
(test harness).
Biblioteki asercji
się od siebie, to zgłaszany jest odpowiedni wyjątek i efekcie cały test kończy
sposób.
Uwaga
w rozdziale 17.
bardziej spójne.
Java.
testu. Przykładami takich narzędzi są RSpec dla języka Ruby, Spectrum dla
Javy, MSpec dla .NET oraz Jasmin i Mocha dla języka JavaScript, które są
i bibliotek.
możemy po prostu napisać nasz własny kod, który będzie wysyłał żądania
testów nie jest ich głównym celem, zwykle nie stanowią one najlepszego
Podczas gdy większość aplikacji projektuje się tak, aby były one
inne programy. Aby jakaś aplikacja mogła być kontrolowana przez inne
klienta.
z aplikacjami.
poczty e-mail itd. Czasem to samo API może być używane przez
jej z tą usługą.
na ślepo odtwarzają one akcje myszy i klawiatury, nie mając żadnej wiedzy
do nich komunikaty, jak gdyby były one wysyłane przez mysz i klawiaturę.
nam osiągnąć ten sam cel. Poniżej znajdują się opisy niektórych
Selenium
Jest to prawdopodobnie najbardziej popularne narzędzie automatyzacji
1. Powiązanie z językiem.
2. Sterownik przeglądarki.
JSON.
„rozumieją” ten sam protokół łączący JSON, ten sam test może zostać użyty
Uwaga
Selenium
Selenium IDE
narzędzia Selenium IDE, tak więc – przynajmniej na razie – nie będzie ono
Appium
Ranorex
Ranorex jest kompletnym narzędziem do automatyzacji interfejsu
postaci kodu. Możemy nawet używać narzędzia Ranorex jako API, które
Microsoft Coded UI
wygodny API. Jest ono dostępne w witrynie GitHub oraz jako pakiet NuGet.
przechowywany jest jako plik XML, zaś każda zmiana dokonana w nim za
do oddzielnego pliku (UIMap.cs), tak aby nie były one przez niego
Uwaga
Aby ułatwić utrzymywanie dużych projektów w programie Coded
interfejsu użytkownika.
Studio Test Professional. Ponieważ jednak nie mamy zbyt dużej kontroli nad
przez firmę Mercury Interactive w maju 1998 roku, po czym w roku 2006
zostało wykupione przez HP. Firma HP zmieniła jego nazwę na UFT w roku
większe firmy.
przystępnej cenie.
SoapUI
SOAP). Istnieją dwie wersje tego narzędzia: (darmowa) wersja open source
oraz wersja Pro, będąca również częścią pakietu ReadyAPI. Wersja Pro
komunikatów HTTP, SoapUI może także tworzyć atrapy dla usług sieci Web
w rozdziale 18).
(będące częścią pakietu Microsoft TFS) oraz Quality Center firmy HP.
w rozdziałach 5 i 15.
firmy Atlassian.
wszyscy wolimy płacić mniej niż więcej… Nie będziemy tutaj wyjaśniać, że
Otóż, jeśli automatyzację opracowuje dla nas tylko jedna lub kilka osób,
za tym idzie, osiągnięcie pełnego pokrycia staje się dla nich dużo trudniejsze
testy mogą zająć sporą ilość czasu, w tym brak odpowiednich umiejętności
czy inwestowanie większej ilości czasu w podstawy, ale również to, że jak
które trzeba zautomatyzować, aby pokryć te nowe funkcje! Nasuwa się więc
zamiast rosnąć, będzie się z czasem zmniejszać. Dlatego, jeśli nie bierzemy
w automatyzację testów!
testy regresji. Dobra wiadomość jest taka, że w dalszej części tego rozdziału
oczywiste.
Tak czy inaczej, jeśli chcemy osiągnąć 100% pokrycia, musimy najpierw
testami manualnymi.
co powinno być pokryte. Nie zawsze jest to prawdą, zwłaszcza jeśli chodzi
w TFS, Jira, Excelu lub jakimś innym programie) wraz z ich opisem, a także
łatwo jest powiedzieć, że każda funkcja, która nie jest powiązana z żadnym
testów, natomiast inna, bardzo złożona funkcja, może mieć tylko jeden
minimalistyczny test…
Ponadto takie listy funkcji (bez względu na to, jak będą one zarządzane)
JAR, EXE itd.), aby móc w czasie uruchamiania wykryć, czy każdy
i uzyskać raport na temat tego, które i jak wiele wierszy kodu zostało lub nie
1. Choć ten sposób dokonywania pomiarów jest dosyć dokładny, a przy tym
inne rzeczy: niektóre po prostu wykrywają, czy dany wiersz kodu został
3. Załóżmy, że udało nam się uzyskać 100% pokrycia kodu i wszystkie testy
kończą się sukcesem. Nadal nie oznacza to, że nie mamy żadnych
błędów. Żeby nie było nieporozumień: to naprawdę świetny wynik!
ale część z nich nie weryfikuje właściwej rzeczy lub nie weryfikuje tak
naprawdę niczego! (tj. sprawdzają one złą rzecz lub wcale nie zawierają
instrukcji Assert).
Listing 4.1. Kod ze stuprocentowym pokryciem, który nadal zawiera błąd
4. Czasem programista napisze jakieś wiersze kodu, które mogą zostać
kodu za niepokryty, mimo że nie jest on osiągalny, ale nie może zostać
DOWODZENIE POPRAWNOŚCI
testami.
2. Mimo że może to potrwać bardzo długo, ważne jest, aby w miarę upływu
ją powiększać.
Przynajmniej nie na tym etapie. Ale nie martwmy się: możemy czerpać
tylko korzyści te będą zauważalne dla naszego szefa, nie będzie większego
produktu zostaną dodane jakieś nowe funkcje, nasze pokrycie kodu znów
spadnie poniżej 100%. Nie dlatego, że mamy teraz mniej automatyzacji, ale
dlatego, że mamy teraz więcej funkcji! Okazuje się więc, że tak naprawdę
wcale nie zakończyliśmy naszej pracy. Co więcej, jeśli jeden lub więcej
testy nadal kończą się sukcesem. W rzeczywistości jest to idealny stan, który
2. Każda zmiana, która psuje istniejące testy, musi zostać jak najszybciej
naprawiona.
cały rok do produktu dodawane były nowe funkcje, więc teraz mamy X
100 (powiedzmy wynosi 150), wówczas pokrycie ich zajmie nam dodatkowe
1,5 roku, ale zanim zdołamy to osiągnąć, będziemy mieli 225 niepokrytych
tyle, ile liczba przypadków testowych, które udało nam się zautomatyzować
100% pokrycia. Sytuację tę pokazano na rysunku 4.2. Tak więc raz jeszcze,
Odwracanie koła
Należy tutaj podkreślić, że im później testy automatyczne tworzone są po
nie są to błędy krytyczne, może minąć kilka tygodni lub nawet miesięcy,
Uwaga
w poprzednim rozdziale.
w którym szybkość tworzenia nowych funkcji jest dokładnie taka sama, jak
które trzeba będzie testować ręcznie. Jeśli jednak luka ta byłaby zawsze na
bardziej wydajne.
Uwaga
produktu.
dwa pytania:
progresji?
ale w praktyce zwykle tego nie robimy ani nie zalecamy. Na początku
zwrot. Aby pierwsze testy mogły działać, musimy zbudować dużą część
zgłoszeniu tego błędu. Jeśli nie uda nam się tego osiągnąć, po prostu
powiązanych z nimi błędów, ale kładźmy nacisk na czas, jaki zajmuje nam
rutynowe badanie tej samej porażki dzień po dniu. Ponadto upewnijmy się,
się, aby nasze testy były łatwe w utrzymaniu. Więcej informacji na temat
Teraz musimy skupić się na pozostałej części testów regresji. I jest tego
bardzo małe ryzyko, że coś w jakiś sposób będzie miało na nią wpływ.
po zmianach tych testy powinny jak do tej pory kończyć się sukcesem.
który został znaleziony nie przy użyciu automatyzacji, należy napisać test
dwukrotnie.
automatyzacji testów nie może być niezależny. Jego cykl życia jest ściśle
wtedy, gdy ktoś z niego korzysta. W przeciwnym razie projekt taki jest
mogą być nieco mniej rygorystyczne, jeśli zespół jest mały i każdy jest
w stanie dostrzec ich zalety. Jednak bez względu na to, czy procesy te są
zmiany, zajmie nam długi czas. Co więcej, gdy wiele testów kończy się
niewiarygodne.
Z tego powodu pierwszą rzeczą, o jaką powinniśmy zadbać, jest to, aby
Najprostsze podejście
z powodu:
błędu w teście,
z perspektywy procesu.
przez jeden lub więcej testów: czyli z powodu wprowadzenia tej zmiany
testy stały się nieaktualne.
Testowanie nocne
nowego testu, przez co nasz kod nie będzie się kompilował lub działał
poprawnie.
wykonanie całego testu nie trwa zbyt długo, możemy sprawić, że testy
śledzenia błędów (np. TFS lub Jira) i pozostawia go tam do chwili, aż ktoś
zdecyduje, że jego priorytet jest wystarczająco wysoki, aby mógł on zostać
naprawiony. Po naprawnieniu tego błędu tester musi już tylko upewnić się,
zostaną one naprawione. Zaletą tego rozwiązania jest to, że rezultaty takich
testów będą przedstawiać prawdziwy obraz dotyczący jakości naszego
przyczyna obu tych niepowodzeń jest taka sama. Jeśli test obejmuje
codzienne badanie wszystkich tych niepowodzeń może stać się dla nas
kolejnych testów.
Uwaga
niepowodzeń testów jest zwykle więcej niż jeden błąd i dla wielu osób
będziemy mogli użyć tego testu, dopóki nie naprawimy tego błędu.
ale testy automatyczne po prostu nie potrafią tego robić. Oznacza to, że
pierwszego błędu.
zmian w czasie, gdy błąd ten był aktywny. Ponieważ mogło minąć
się, że kod, który nie jest uruchamiany przez długi czas, po prostu
powyższe wady należy przemnożyć nie tylko przez każdy błąd, ale też
dnia. Tak czy inaczej, błędy zarządzane są w systemie śledzenia błędów, tak
więc nie musimy się tym przejmować każdego dnia. Podejście to ma jednak
wszystkie te testy.
a dzisiejszym (np. wczoraj test kończył się w kroku 3, a dziś kończy się
w kroku 2), w tym podejściu nie możemy nawet tego zobaczyć,
się, że kończy się pomyślnie, nie jest zalecane. Ponadto nie są nam
dokonują.
krok pośredni w teście, a nie na całą istotę tego testu. Zwykle jest ono
błędów.
Jeśli problem ma wpływ na wiele testów, a automatyzacja jest
w jednym miejscu.
ignorowanych.
OPTYMALNE PODEJŚCIE?
trudniejsza w użyciu.
realistyczne:
zmianami. Jeśli tak czy inaczej w pewnym momencie będą one musiały
naprawić błąd.
Uruchamianie testów co noc oraz angażowanie deweloperów i zarządu
opcją. Może to oznaczać wiele operacji check-in, zwłaszcza jeśli zespół jest
wakacje…
Ciągła integracja
się sukcesem. Proces, który kompiluje kod i uruchamia testy, zwykle działa
zmiany.
kto, kiedy i jak powinien uruchamiać testy, nie daje ona odpowiedzi na
następujących koncepcjach:
skierować ją do produkcji.
Zaletą tej techniki jest to, że gwarantuje ona zaangażowanie się testerów
projektu, wiele z jego zalet będzie mniej oczywistych, ale na dłuższą metę
nadal nam się to opłaci. Rozdział 16 zawiera porady, które pomagają nam
łańcuchem dostaw…
zbioru stron HTML lub w innej formie, takiej jak plik PDF. To, wraz
i dystrybucji.
wdrażania, który może wtedy zostać użyty przy wdrażaniu nowych wersji
ciągłym wdrażaniem.
dostarczaniem.
SaaS19 oraz inne aplikacje sieci Web, które nie są uznawane za krytyczne
Wydania kanarkowe
Jeśli coś pójdzie nie tak, wówczas taki węzeł może zostać odłączony do
czasu naprawy tego błędu. Jeśli wszystko działa poprawnie, możliwe jest
klientów programu beta. Jeśli po jakimś czasie nie zostaną wykryte żadne
rozdziale.
Testowanie A/B
Kolejnym pojęciem, które często wykorzystywane jest przez dostawców
dużych aplikacji sieci Web jest testowanie A/B. „Testowanie A/B” jest
klientów udostępnia się inny wariant tego samego produktu, który różni
Podsumowanie
testów.
Rozdział 6. Automatyzacja
i architektura testów
na cały system i które trudno jest już potem zmienić. W przypadku systemu
są pisane, jak są one uruchamiane, co mogą robić, a czego nie, itd. Jednak
architektura automatyzacji testów powinna również brać pod uwagę
1. Kto powinien napisać test i jakie umiejętności powinny mieć takie osoby?
wiarygodny?
wejściowym.
Uwaga
Niektórzy ludzie myślą, że uczenie maszynowe oraz inne
incydentu jako błędu. Co więcej, jeśli nawet usługa ta jest aktywna, to często
usługi zewnętrznej, tak więc tester manualny może określić, czy są one
poprawne, czy nie, przy czym nie może on wcześniej przewidzieć, jakie
powinny być te wartości wyjściowe. Ale jak już wiemy, dla automatyzacji
testów to, czy coś ma sens, nie jest żadną opcją, ponieważ musimy być
poprowadzić taką linię podziału. Ponieważ dla tej operacji nie istnieje żaden
może się nam teraz wydawać niemożliwe, ale w dalszej części tego
dane. Oczywiście takim źródłem danych mogą być również pliki, urządzenia
dane do bazy danych, która może potem zostać użyta przez inny system do
danych jako źródło danych, które powinno być kontrolowane przez test.
opisywanych w rozdziale 7.
i czynników, które zaraz sobie omówimy, podając przy tym wady i zalety
który definiuje cel oraz kroki konkretnego testu. Innymi słowy, za pomocą
technicznych, takich jak opis tego, które dokładnie przyciski kliknąć, aby
wydawać się dobrym pomysłem, tak naprawdę sprawia, że testy stają się
39,99 dolara
w wysokości 10 dolarów
– 10).
promocji czy dodania książek do koszyka zakupowego. Dzięki temu test ten
skorzystać z więcej niż jednej takiej opcji, oraz jaki niesie to ze sobą koszt.
Choć w powyższym typowym przykładzie scenariusz można
Omówienie warstw
znajduje się logika biznesowa. Warstwa dolna jest relacyjną bazą danych
poniżej.
Warstwa klienta
języka znaczników, takiego jak HTML, XML lub XAML. Jeśli warstwa
biznesową.
kodu.
pomijając już te procedury i to, że silnik bazy danych sam w sobie jest
jest to, że jest ona najbardziej zbliżona do tego, co robią użytkownicy i nie
testów tak czy inaczej nie będzie stanowić dla nas zbyt dużej wartości,
wszystkie inne testy kończą się sukcesem, może okazać się cenne, ale
na kompletnym systemie.
jest cały system, tak więc z technicznego punktu widzenia jest to taki sam
takie same zalety i wady jak opcja zakresu kompleksowego, ale istnieją
którego nigdy nie był projektowany i który nigdy nie będzie miał miejsca
w produkcji.
Kolejnym ryzykiem, jakie należy wziąć pod uwagę, jeśli opieramy się na
technologii, która może się w całości zmienić. Gdy nasze testy wchodzą
dosyć rzadko, to jeśli planujemy długi czas życia dla automatyzacji testów,
dzisiaj wiele zespołów zastępuje swoje silniki baz relacyjnych (SQL), takie
jak Microsoft SQL Server czy Oracle, jakimiś alternatywami „nie SQL-
danych. W takim wypadku ważne jest, aby upewnić się, że to, co robią
serwera proxy lub wysłanie żądań HTTP, bądź też przy wykorzystaniu
wystarczająco prosty.
Rysunek 6.7. Zakres kompleksowego testu jednokierunkowego
Klient zmienia się znacznie częściej niż API lub protokół, za pomocą
operacyjnych, dla sieci Web, mobilne itd.) i wszystkie oferują takie same
AUTOMATYZACJI TESTÓW
prostsze niż zwykle, ponieważ nie muszą się oni tak bardzo
zmieniać.
z każdym wpisem.
mogą zostać dodane nowe funkcje i rozwiązania, ale nic nie powinno
zostać usunięte, jak również nie powinno być żadnych zmian, które
psułyby dotychczasową funkcjonalność. Zwróćmy uwagę, że samo
każdy taki abstrakt składał się z co najmniej 100 znaków, żeby można
go było wypełnić jakąś istotną teścią. Tak długo, jak będzie to mieć
dla tego przykładu jest rezygnacja z wymuszania tej reguły dla postów
podstawie ich tytułów, to może nie być w stanie ich odnaleźć, ponieważ
tytuły tych wpisów zawierają teraz prefiks „AUTO” i nie zgadzają się
Choć w teorii 100% testów, które kończą się sukcesem w jednej wersji,
serwerem, test komunikuje się z serwerem poprzez jego API, ale podobnie
komponentami.
Na przykład:
Gdy serwer jest starszym lub zewnętrznym systemem, który nie będzie
etapie rozwoju.
Gdy klient jest tylko jednym z wielu klientów, a serwer testowany jest
dobrego interfejsu automatyzacji lub po prostu nie jest dość wiarygodna dla
wybierze jakąś inną opcję, która to realizuje. Jednak testy zachowują się
dopóki prawdziwy użytkownik nie zamknie tego okna. Jeśli wzorzec ten
zaimplementowany jest poprawnie, wówczas obsługa zdarzeń nie
powinna otworzyć tego okna bezpośrednio, lecz użyć w tym celu obiektu
użytkownika.
Co prawda podejście to nie jest to zbyt popularne, jednak wydaje się ono na
Testy komponentów
zależny.
Testy jednostkowe
Rzeczywista architektura
aplikacja jest inna i dzisiaj większość systemów jest od niej dużo bardziej
tych przeszkód zwykle sprawia, że kod testu staje się bardziej złożony,
kod…
Typowe warianty
także różnią się od siebie, głównie tym, jak wiele logiki znajduje się po
aplikacji.
2. Wiele aplikacji obsługuje więcej niż jeden rodzaj klienta. Mogą one mieć
rozdziału.
Selenium.
Łączenie testów
Mieszanie i dopasowywanie
porcji testów lub określić kryteria wyboru zakresu dla każdego testu.
Choć nie jest to jedyne wyjście, jednak wydaje się być odpowiednie
zakres będzie lepiej pasował do konkretnego testu, tak więc mogą pojawić
adapter między testem a testowanym systemem. W ten sposób sam test nie
Podsumowanie czynników
ale kiedy przyjdzie nam wybrać tylko jeden z nich, to nadal możemy mieć
Osiągalność
równania. Czynnik ten sprowadza się do zadania pytania: „Jak ważne jest,
użytkownika jest bardzo cienka, nie zawiera żadnej logiki i jest edytowana
nasz test za każdym razem, gdy tak się stanie. Oczywiście ten czynnik
dotyczy każdego komponentu, który nie zawiera w sobie zbyt wiele logiki,
lub który został już przetestowany i nie jest już nigdzie modyfikowany.
Szybkość
czynnik ten może nie być tak bardzo istotny, chyba że proces ich
zmian, wówczas nie możemy oczekiwać, że będą oni czekać kilka godzin na
wady i ograniczenia).
znaczenia, gdyż inne czynniki mogą być od niej dużo ważniejsze. Ponadto
kompleksowe lub integracyjne mogą być bardzo szybkie, jeśli nie opieramy
maszynie.
nasze testy również musimy stale aktualizować. Jeśli jednak cały interfejs
Mimo że jest to bardzo istotna kwestia, którą należy brać pod uwagę,
Ograniczone zasoby
ale nie będą oni w stanie naprawić lub tworzyć nowych testów – co
ludzi i narzędzi.
zwykli użytkownicy mogą zmieniać jej domyślne działanie, nie mając przy
testów dostępny był jedynie niewielki podzbiór tych pól, zaś w pozostałych
domyślne rozszerzenia mogą, ale nie muszą, być używane przez klienta.
musieli skorzystać.
Symulatory
czym nie chcemy testować tego komponentu. Symulatory mają kilka zalet:
możemy kontrolować.
Mogą być używane do weryfikowania, czy testowany system wysyła
ocenić to, jak kontrolowane przez nas parametry fizyczne powinny wpływać
właśnie prognozę zobaczy nasz system, dzięki czemu będziemy mogli łatwo
interfejs dla testowanego systemu musi być dokładnie taki jak w przypadku
procesu testu, czy też w pamięci tego oddzielnego procesu symulatora), aby
asynchroniczny.
odpowiada przy użyciu tej samej odpowiedzi lub który zawiera w sobie
odpowiedzi, ale nie może być kontrolowany przez test. Co prawda istnieją
wadą jest to, że nie mamy tak naprawdę kontroli nad danymi dostarczanymi
wewnętrzna logika staje się coraz bardziej złożona, gdy staramy się, aby
całego protokołu naraz, lecz tylko jego minimalną część, niezbędną dla
opiera się na zegarze systemowym, wówczas ważne jest, aby wszystkie one
na to, czy przeczytamy ten dodatek, czy nie, powinniśmy teraz dysponować
pewne problemy. Jest tak, ponieważ zwykle istnieje więcej niż jeden
która naszym zdaniem będzie najlepsza dla nas i dla naszej organizacji.
zainicjalizować system!
jednak miało miejsce tylko wtedy, gdy aplikacja kalkulatora została przed
Stan
stan”. Oznacza to, że aby nasze testy były wiarygodne, musimy mieć pełną
kontrolę nie tylko nad samymi danymi, ale także nad stanem testowanej
przypadkach.
innymi):
dysku.
Windows.
5. Zdalne dyski twarde. Działają podobnie jak dyski lokalne, ale dyski te
odpowiedniej izolacji.
Problem 1 – testy manualne i test automatyczny
wykonywane w różnym czasie
jest Kathy. Pierwszym napisanym przez nią testem był test poprawności
cena wynosi 100 dolarów, oraz produkt „Mikrofon”, którego cena wynosi
50 dolarów. Zadaniem tego testu jest sprawdzenie, czy całkowita suma cen
produktów w koszyku wynosi 150 dolarów. Test ten był bardzo stabilny
i przez długi czas był wykonywany jako część zestawu testów poprawności
jakiegoś błędu?).
jest młody i nie ma w nim zbyt wielu testów, częstotliwość takich zdarzeń
jest dosyć niska i mogą one zostać naprawione zaraz po ich wystąpieniu.
Inny test napisany przez Kathy weryfikuje, czy po złożeniu przez klienta
jeszcze stan zapasów i weryfikuje, czy liczba sztuk tego produktu została
(„test1”, „test2” itd.), które po zakończeniu testu były usuwane. Od tej pory,
faktury nadal pokazywać będą ceny oryginalne (jest to ten sam test,
Przez kilka nocy oba te testy działały bez żadnych problemów. Pewnego
dnia Kathy zauważyła, że nazwa testu napisanego przez Boba nie jest zbyt
jakiś błąd, który został już rano naprawiony?) i że niepowodzenia tego nie
się przed testem poprawności, podczas gdy przed zmianą tej nazwy test
podobnie jak miało to miejsce w przypadku, gdy John uruchamiał ten test
ręcznie.
Jednak Bob nadal nie rozumiał, dlaczego testy nie kończyły się
potrzebny na ich wykonywanie stał się zbyt długi, Kathy zdecydowała się
na podzielenie tych testów na cztery grupy i uruchamianie każdej z nich
okazjonalnie testy, które były do tej pory stabilne, zaczęły kończyć się
Techniki izolacji
w różnych zespołach liczba, nazwy oraz cele tych środowisk mogą być
inne. Każde takie środowisko zawiera zwykle swoją własną kopię bazy
danych.
niepowodzeń.
założenie to może bardzo szybko stać się błędne, a utworzone przez nas
natury środowiska.
oddzielnego środowiska.
to, że system jest zbyt duży, aby można go było umieścić na maszynach
rozmiary, jest baza danych. Ale tak naprawdę zwykle automatyzacja nie
podejścia).
nie jest zwykle możliwa, to często możliwe jest wykonanie tego raz przed
każdym cyklem testowania (np. przed rozpoczęciem testów nocnych lub
program.
Jednym z pytań, które nasuwają się przy rozważaniu tych rozwiązań jest
to, czy resetowanie stanu powinno mieć miejsce przed czy po wykonaniu
kopii zapasowej.
plików kopii zapasowej w takim systemie jest to, że pliki kopii zapasowej
będą one zapisywać pełne pliki dla każdej pojedynczej zmiany. Oznacza to
Cofanie transakcji
Kolejną techniką izolacji, która wykorzystuje bazę danych i podpada pod
krótki.
się z bazą danych, tak więc test powinien otworzyć połączenie, rozpocząć
wiele maszyn wirtualnych, dlatego też w tym celu często stosuje się
a czas potrzebny na jej włączenie jest podobny do czasu, jaki potrzebny jest
wirtualnych.
wirtualnej, a nie tylko jej dysku twardego, tak więc można ją zrobić
ponieważ każda maszyna musi mieć inną nazwę, inny adres IP, inny
aby to obsłużyć, ale jeśli jest, to firmy mogą zwiększać dostępne ilości
testu. Jeśli każdy test tworzy i wykorzystuje własne dane, to jeden test nie
jest ustalenie tego, które dane mogą być współdzielone, a które nie
i test ten kończy się sukcesem, ale w nocnej kompilacji sławne już testy
daleko: większość aplikacji używa zestawu danych, który bardzo rzadko się
dosyć rzadko, niemniej jednak lepiej będzie utworzyć nowy produkt dla
każdego testu.
fragment informacji powinien być tworzony przez każdy test lub może być
zastosowań.
Czy większość testów może działać poprawnie, jeśli istnieje tylko jedna
produktu.
naprawdę konieczna, czy też nie. Jeśli jest, zamieniamy dane fikcyjne na
zająć trochę czasu, ale nie jest to bardzo skomplikowane. Jeśli się to uda, to
systemu i testów.
Jest nawet wysoce prawdopodobne, że na początku system ten nawet się nie
rodzaju aplikacji:
dodajemy brakujące dane jako część kodu testu. Jeśli nie, to należy
wspólne dla wszystkich kont (np. kraje, waluty itd.), a które mogą
cyklem testowania”).
Jeśli aplikacja jest witryną (aplikacją publiczną lub wewnętrzną), ale nie
utworzyć test, zaś dane, które mogą być modyfikowane wyłącznie przez
testy w sposób, który ułatwi nam ich utrzymanie, jeśli pewnego dnia
te dane, na których opierają się nasze testy. Upewnijmy się, że nasz test
to, że dane te faktycznie nie były już potrzebne. Jeśli jednak test kończy
pewien globalny stan lub gdy jakaś jednostka tworzona przez jeden test
może mieć wpływ na inne testy, mimo że te testy nie korzystają z niej
przez pierwszy test. Z tego powodu zaleca się również, aby każdy test
Okazuje się jednak, że sposób ich działania niezbyt dobrze nadaje się do
1. Klasa testowa może zawierać więcej niż jeden test. Mimo że testy w tej
zgłosi wyjątku), jednak bez względu na to, czy sam test zakończy się
pierwszej jednostki powiedzie się, ale drugiej już nie. W takim wypadku
3. Często jest tak, że to sam test tworzy jakąś jednostkę. Nie ma z tym
kolejności (aby rozwiązać problem nr 4). Naturalnie, gdy test kończy się
dane te nie powinny być traktowane jako stan, ale jako dane stanowiące
wejście. Z tego powodu nie musimy tak naprawdę izolować od siebie
pytania:
klientów.
jak również wiele innych założeń co do naszych testów, nie będą już
powiedzieć, że to, co widzimy dziś, było takie przez wiele lat i nikt jak
dotąd nie narzekał, tak więc można to uznać za poprawne. Zgoda, ale
kod jest poprawny, czy nie (a jeśli kod nie będzie modyfikowany, to
Podsumowanie
ale również jego stan. W tym rozdziale omówiliśmy różne techniki izolacji
testów jest z nimi połączona oraz jak to wszystko jest ze sobą powiązane.
akapicie tej pracy zamieścił on pewną maksymę, która później stała się
Prawo Conwaya
zespole zwykle komunikują się ze sobą częściej, a fragmenty ich pracy (np.
struktury formalnej: jeśli dwie osoby z tego samego zespołu lub różnych
programiści mogą tworzyć kod, który będą w stanie zrozumieć tylko oni.
użytkownika, a pod nim znajduje się warstwa biznesowa. Niżej znajduje się
z bazą danych, zaś na samym dole – sama baza danych. Każda z tych
Z kolei wadą tej metody jest to, że prawie każda funkcja jest
interfejs użytkownika, bazy danych, logika biznesowa itd.), ale wszyscy oni
pracującego nad stroną klienta (miał to być „klient zubożony”, stąd też
funkcji.
w rozdziale 6.
jedynie ich własną warstwę. Nie chcą zajmować się błędami, które nie
zjawiska jest to, że gdy coś pójdzie nie tak, zespoły zaczynają obwiniać się
jeśli coś nie będzie działać, to zespół A będzie w stanie udowodnić, iż wina
że pisanie testów dla innego zespołu nie jest efektywne, ponieważ testy
testów i sprzyja zaufaniu między tymi zespołami, gdyż będą one w stanie
terminy.
W ogólnym przypadku dowolna technika, narzędzie i praktyka
modułu.
Przy użyciu tej lub podobnej techniki, struktura zespołów nieustannie się
(squad).
testów tak, aby obejmowały wszystkie istotne moduły, jakie muszą zostać
zmienione dla tej funkcji. Podejście to jest dosyć trudne, ale jeśli uda się je
konkretnej funkcji. Do tego celu bardzo dobrze nadaje się metodyka ATDD
chodzi o zwrot inwestycji z testu (tj. jaką wartość wniesie dany test
W dużych zespołach warto zadbać, aby taka osoba miała rolę niezależnego
Podsumowanie
nam się nie tylko stworzyć najlepszą automatyzację testów dla naszej
testów, może odcisnąć swoje piętno na organizacji i stać się liderem. Więcej
organizacji (nawet bez upoważnienia), oraz tego, jak stać się liderem,
świata automatyzacji testów, wyjaśniając przy tym, czym jest, a czym nie
projektu.
samouczka.
z utrzymaniem.
programowania C#. Lepsza znajomość języka Java lub Python, nawet bez
ponieważ większość zasad będzie zawsze taka sama, bez względu na to,
http://www.TheCompleteGuideToTestAutomation.com.
Poza wyborem języka C# jako naszego języka programowania,
żadnych testów ani też nie był pisany z myślą o jego testowaniu,
takie same również dla innych zakresów testowania. Nie martwmy się
zatem, jeśli nie jesteśmy zaznajomieni z narzędziem Selenium lub jeśli nasz
projekt nie jest aplikacją sieci Web. Jak wspomnieliśmy, większość tych idei
i koncepcji pozostaje taka sama nawet dla testów, które nie mają żadnej
infrastrukturę, tak aby były one łatwe w utrzymaniu. Mimo że proces ten
Omówienie procesu
przez wiele lat i z którego skorzystało już wiele osób. W ramach kilku
uzyskać pełny obraz tego, jak należy z niego korzystać. Zanim jednak
wady, jeśli chodzi o łatwość utrzymania. Z tego powodu zaleca się, aby cały
potrzebny w tym teście i nic poza tym! Gdy zrobimy tak z pierwszym
Proces
tego procesu bądź wtedy, gdy wszystkie testy będę się już poprawnie
7. Wróć do kroku 4.
szybciej.
należą:
silnik motywów,
zarządzana za pomocą samej tej aplikacji (witryna ta nie jest pod naszą
kontrolą, tak więc używana w niej wersja aplikacji może być nowsza, a sama
9.2).
rozwiązania jeszcze tam nie ma, możemy zadać na tej stronie nowe pytanie
dostępną wersją programu Visual Studio była wersja 2017. Visual Studio
elementy:
platformy .NET)
ASP.NET and Web Development (Opracowywanie zawartości dla
zainstalujemy Visual Studio bez tych pakietów roboczych lub mamy już
jej informacji. Jeśli nie mamy zainstalowanej żadnej edycji bazy danych
W czasie pisania tej książki najnowszą wersją tego systemu był SQL Server
us/sql-server/sql-server-editions-express.
Ważne
1. Gdy uruchomi się kreator instalacji, jako typ instalacji wybierz Basic
(Instalacja podstawowa).
kreatora.
2. Powinien uruchomić się program Visual Studio (jeśli nie był uruchomiony
9.5 (jeśli z jakiegoś powodu tak się nie stanie, możesz otworzyć ten
C:\TheCompleteGuideToTestAutomation\MVCForum, jak to
(Sklonuj).
Rysunek 9.5. Klonowanie repozytorium GitHub do lokalnego komputera
rozwiązania MVCForum.sln.
OK.
informacja:
Uwaga
Chrome
ponownie).
rysunku 9.7.
rozpoczęcia samouczka.
Uwaga
sobie życia bez niego. W ramach tego samouczka pokażemy, w jaki sposób
możemy z niego korzystać, a także jak osiągać te same cele bez użycia tego
z tego dodatku!
niż jedną wersję programu Visual Studio, będziesz mógł wybrać wersje,
instalacji.
OK.
Uwaga
części dni jako pełne dni. Ponadto, jeśli nadal otwarta będzie inna
kontynuowany.
Wskazówka
w dodatku D.
gdy coś pójdzie nie tak, będziemy chcieli porównać swój kod z kodem
SourceTree itd.). Jeśli nie znamy tego systemu zbyt dobrze, możemy
gałąź, na którą chcemy się przełączyć (np. master lub Tutorial). Zwróćmy
przełączamy się do innej gałęzi, zawsze jest brana pod uwagę najnowsza
w ramach tej poprawki. Z tego miejsca możemy porównać każdy plik z jego
poprzednią wersją lub otworzyć go, aby zobaczyć, jak wyglądał on w tej
polecenia).
została wyewidencjonowana.
Podsumowanie
samouczka. Warto nie tylko przeczytać ten samouczek, ale też robić na
pomysły, jak powinien wyglądać taki pierwszy test, lub nawet wybrali już
dosyć często. Ale kryteria dotyczące tego, w jaki sposób testy te zostały
definicja tego, co tak naprawdę powinien zawierać taki zestaw, może się
pytania:
klientów/użytkowników?
dodatkowych:
Jakie będą szkody, jeśli system przestanie działać?
oszczędzać?
i gdzie?
ważne pytanie:
przetestować?”
nie daje odpowiedzi na te pytania. Oto kilka przykładów testów, które nie
są dobrymi kandydatami na pierwsze testy, czy też w ogóle na testy
automatyczne:
szczegółami, znajduje się na tej stronie, bądź też – co może być jeszcze
zamówienie!
to, aby umożliwić jego użytkownikom logowanie się do niego, tak samo
układu kontrolek, ale nadal nie jest to celem, dla którego budowane są
kątem tego, czy są włączone lub wyłączone, nie tylko nie mówi nam
zbyt wiele, ale też może zostać w łatwy sposób popsute, jeśli
FUNKCJĘ?
produkcyjnym).
przetestować?”
mają na ten sam lub nawet inne wyniki. Domyślnym sposobem udzielenia
wszystkim) – przez co również i one powinny być brane pod uwagę przy
scenariusz.
znaleźć jeden taki kontrprzykład, aby obalić czyjąś teorię! Jednak w miarę
jak coraz więcej naukowców wykonuje dla danej teorii kolejne testy
kontrprzykładu, teoria taka staje się coraz bardziej stabilna i uznawana jest
za „prawdziwą”.
Twierdzenie takie jest zdaniem, które jest albo prawdziwe, albo fałszywe.
Zwykle pod definicją taką dodajemy wiersz złożony ze znaków „=”, aby
oznaczyć w ten sposób tytuł tego testu. Zwróćmy uwagę, że metoda ta jest
interpretacjom.
twierdzenie obalić.
i „szum” mogący mieć wpływ na nasz wynik, które nie mają żadnego
Chcemy również, aby nasz eksperyment był tak prosty i krótki, jak to
odtworzyć.
Istnieje jednak pewna mała różnica pomiędzy eksperymentem
użyjemy domyślnych wartości dla rzeczy, które być może będziemy musieli
Uwagi:
znaczenia.
tytułu. Dzięki temu, nawet jeśli uruchomimy nasz test wiele razy (lub
Category”, albo też dodać kolejną kategorię, która będzie używana jako
można było łatwo zmienić tę decyzję. Tak czy inaczej, powinno to być
wymaganiem wstępnym testu, a nie częścią samego testu. Później
przełożenie tych kroków na kod. Aby jednak kod ten był łatwy
kontekst dla operacji opisywanej przez ten wiersz. Kontekst ten lepiej
terminy te wydają się mieć sens dla większości ludzi, a ponadto mają
pewnego doświadczenia.
W wielu przypadkach, wliczając w to również nasz przykład,
UWAGI (*)
implementację.
samej górze), tylko wtedy, gdy nikt poza nami nie używa tego samego
środowiska. Zajmiemy się tym później w ramach naszego rozwiązania
7).
Modelowanie aplikacji
class Customer {
public IList<Order> Orders { get {
/*...*/ } }
public Order CreateOrder()
{
//...
}
//...
}
class Order {
public IList<Product> Products { get {
/*...*/ } }
public void AddProduct(Product product)
{
//...
}
public void Submit()
{
//...
}
//...
}
class Product {
public string Description { get {
/*...*/ } }
public decimal Price { get { /*...*/ } }
//...
}
obszarze interfejsu.
Jeśli będziemy chcieli później zmienić jakieś operacje, tak aby były one
w utrzymaniu:
który reprezentuje ten nowy widok. Dzięki temu kod będzie dużo
powinien mieć swój własny obiekt strony. Idea ta może nawet zostać
oraz w kodzie.
Rysunek 10.1. Zagnieżdżone obiekty strony
class MainPage
{
// ...
public ToolbarView ToolBar { get {
/*...*/ } }
public FoldersTreeView FoldersTree { get
{ /*...*/ } }
public HeadersListView HeadersList { get
{ /*...*/ } }
public PreviewPane PreviewPane { get {
/*...*/ } }
}
class ToolbarView
{
//...
}
class FoldersTreeView
{
//...
}
class HeadersListView
{
//...
}
class PreviewPane
{
public MessageHeaderView MessageHeader {
get { /*...*/ } }
public MessageBodyView MessageBody { get
{ /*...*/ } }
}
class MessageHeaderView
{
//...
}
class MessageBodyView
{
//...
}
Listing 10.5. Obiekty strony dla typowej aplikacji głównej
tej samej klasy obiektu strony. Oznacza to, że należy unikać używania
jednoczesnych użytkowników!
Istnieją takie widoki, które pojawiają się w różnych miejscach
wspólnego, ale w pewnych aspektach różnią się między sobą, więc ich
Jak już wspomniałem, nie trzymam się sztywno wzorca obiektu strony.
zrozumienia produktu.
na API lub na jakiś inny zakres, będzie to znacznie prostsze, ponieważ nie
jednak często separacja nie jest tak duża, jak byśmy chcieli, tak więc
możemy zamiast tego pisać testy jako testy systemu (więcej informacji na
w rozdziale 6).
metody testowe.
dla naszego kodu testu. Choć nie napisaliśmy jeszcze ani jednego wiersza
własnych doświadczeń.
Rozdział 11. Kodowanie pierwszego
testu
się sukcesem. Wiele fragmentów pisanego przez nas kodu posłuży również
Tworzenie projektu
Aby napisać test, musimy najpierw utworzyć dla niego nowy projekt.
pomysłem, ale ponowne użycie pewnych rzeczy, takich jak stałe czy nawet
ponieważ przy każdej modyfikacji stałej trzeba również zmienić jej wartość
w testach…
(Nowy Projekt).
Uwaga
MSTest.
dodany do projektu. Projekt ten zawiera plik UnitTest1.cs. Kliknij ten plik
dwukrotnie, aby otworzyć go w edytorze kodu źródłowego. Wygląd tego
Uwaga
testów, ale wykraczają one poza zakres tej książki. To tylko część informacji
wiedzieć.
Test Explorer (jeśli nie został otwarty wcześniej) za pomocą opcji Test
widoczna przy jego nazwie ikona powinna po kilku sekundach zmienić się
Uwaga
Sytuacja, w której test zakończył się sukcesem, mimo że był
niepowodzeniem.
Wskazówka
tylko jeden z nich, ale nic nie stoi na przeszkodzie, aby zrobić to
pomysłem, ponieważ nazwa ta tak naprawdę nic nam nie mówi. Musimy
zmienić zarówno nazwę tej klasy, jak i nazwę samego pliku, w której się ona
od razu zmienić nazwę pliku tak, aby pasowała ona do nazwy zawartej
w nim klasy:
1. W edytorze kodu kliknij dwukrotnie nazwę klasy (UnitTest1), aby ją
zaznaczyć.
file to match type name (Zmień nazwę pliku, aby pasowała do nazwy
typu).
Wskazówka
edytujemy ją w taki sposób, aby jej nazwa odzwierciedlała test, jaki jest nam
znaki spacji i rozpocząć każde kolejne jego słowo od wielkiej litery (czyli
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace MVCForumAutomation
{
[TestClass]
public class SanityTests
{
[TestMethod]
public void
WhenARegisteredUserStartsADiscussionOther
AnonymousUsersCanSeeIt()
{
}
}
}
Uwaga
Pisanie pseudokodu
i identyfikatory nie są w nim obecne. Z tego powodu na tym etapie kod taki
prawdziwym kodem.
komentarza.
Rysunek 11.3. Pisanie pseudokodu
Uwaga
Jak widać, utworzony przez nas pseudokod jest poprawną składnią języka
C#, mimo że nadal kod ten nie kompiluje się z powodu wielu brakujących
w ten sposób osiągnąć i nie sprawić przy tym, że kod będzie bardziej
problematyczny.
Discussion:
Zadeklarowałem dwie zmienne typu
takie same, nie możemy tego zakładać w teście, ponieważ jest to coś, co
nie musimy jawnie określać jej typu. Aby skorzystać z tej możliwości,
ponieważ kompilator ustala jej typ już na etapie kompilacji i nie może
zmienna taka nadal jest silnie typowana (tj. jej typ jest statyczny), tak
więc jeśli spróbujemy wywołać metody lub uzyskać dostęp do
Gdy sam piszę pseudokod dla testu, zwykle stosuję w nim słowo
kompilował.
będącego strukturą klas i sygnatur metod, ale bez pisania żadnego kodu
również będzie niska! Skupmy się więc na bieżącym kroku: sprawmy, aby
Wskazówka
większą kontrolę nad tworzeniem klas i metod. Istotne jest zwłaszcza to, że
zwracanych przez metody, aby może je było edytować, podczas gdy Visual
nazwy oraz typy, które jest w stanie sam wywnioskować, dlatego nie zawsze
są one takie, jak byśmy tego chcieli. W takim wypadku musimy ręcznie
zmieniać je ręcznie.
Wskazówka
tworzenia nowej klasy mamy opcję utworzenia jej albo w oddzielnym pliku,
w którym kod poprawnie się skompiluje lub pierwszy test zakończy się
Pierwszy błąd kompilacji, na jaki się natkniemy, mówi o braku definicji typu
kontekstowego
object, ponieważ ani Visual Studio, ani ReSharper nie wiedzą, jakiego
typu powinna być ta właściwość. Ale ReSharper dodatkowo umieszcza
metodę ustawiającą (nie trzeba będzie tego robić, jeśli zastosowaliśmy się do
MVCForumClient
Uwaga
w dodatku D.
kod. Później zobaczymy, w jaki sposób możemy zamienić treść tej metody
programowania dla innych języków treść ta pozostaje czasami pusta (lub jest
CreateDiscussion, to
jeśli spróbujemy utworzyć najpierw metodę
w następującej kolejności:
klasy DiscussionBuilder.
Gdy nasz kod wygląda jak na listingu 11.3, powinien się on już
powiodła się) na pasku stanu w dolnej części ekranu. Jeśli kompilacja nie
powiedzie się, wówczas pojawi się panel Error List (jeśli tak się nie stanie,
Uwaga
klasie w każdym pliku. Upewnijmy się, że po tej zmianie nasz kod nadal się
kompiluje.
mogła sprawdzić:
i tworzoną aplikację.
4. Jeśli nie jest to pierwszy test, to czy nie istnieją już podobne metody lub
Podsumowanie
ilość kodu, który w zasadzie niczego nie robi, to utworzyliśmy tak naprawdę
szkielet (lub projekt) dla testu i jego kodu infrastruktury, zapewniając jego
staraliśmy się trzymać opisu testu, kod metody testowej okazał się bardzo
Dobrze, skoro nasz kod już się kompiluje, to czym powinniśmy się teraz
zająć?
wybuchnie! Cóż, racja, nie będzie to działać. Ale również nie wysadzi to
Ponadto jest to również dobry sposób na to, aby upewnić się, że nasze testy
itd. Będzie to miało duże znaczenie później, gdy będziemy chcieli uczynić je
otwieramy panel Test Explorer (jeśli nie jest jeszcze otwarty) za pomocą
został zgłoszony. Domyślnie ten dolny obszar panelu jest dosyć mały, ale
rysunku 12.1.
Rysunek 12.1. Panel Test Explorer pokazujący pierwsze niepowodzenie
testu
MVCForumAutomation.
SanityTests.WhenARegisteredUserStartsADiscussionOtherAnonymous
Choć wygląd tego komunikatu może zniechęcać, to tak naprawdę nie jest
która nie dość, że sama w sobie jest długa, to prezentowana jest tu w pełnej
jeszcze skompiluje nasz kod, tak aby przy kolejnym uruchomieniu testu
Uwaga
okna.
wyników, dopóki nie wpiszesz całego słowa. Powinny teraz pojawiać się
zapytania „Selenium”
Zaznaczamy kolejno każdy z pierwszych trzech wyników
testu.
Uruchamianie IISExpress
"%ProgramFiles(x86)%\IIS Express\iisexpress.exe"
/path:C:\
TheCompleteGuideToTestAutomation\MVCForum\MVCForum.
Website\
z której korzystamy.
Zakładając, że IISExpress uruchomiło się poprawnie, możemy teraz
przeglądarki.
Implementowanie konstruktora
MVCForumClient
public MVCForumClient()
{
var webDriver = new ChromeDriver();
}
NotImplementedException w metodzie
została ona jeszcze zaimplementowana. Ale zmieniło się to, że teraz przy
Uwaga
dodamy znak podkreślenia, tak więc pole to będzie teraz nosić nazwę
_webDriver.
Jeśli używamy narzędzia ReSharper, możemy automatycznie
z listingu 12.2.
public MVCForumClient()
{
_webDriver = new ChromeDriver();
}
~MVCForumClient()
{
_webDriver.Quit();
}
public MVCForumClient()
{
_webDriver = new ChromeDriver();
_webDriver.Url = "http://localhost:8080";
}
Implementowanie metody
RegisterNewUserAndLogin
z techniki „od góry do dołu”, której użyliśmy do napisania testu, lecz tym
registrationPage.Register();
MVCForumClient.RegisterNewUserAndLogin
Uwagi:
Hasła i adresy e-mail nie muszą być niepowtarzalne ani też realistyczne.
RegistrationPage
Wszystkie metody ustawiające wartości w klasie
Jak nietrudno zgadnąć, musimy teraz sprawić, żeby nasz kod ponownie
znajdujący się w górnej części strony (w pobliżu łącza Log On). Na rysunku
kolejną uwagę), ale najważniejszą regułą jest to, że lokalizator musi pasować
programistów
Wskazówka
odpowiedniego lokalizatora.
zmiany tego tekstu nasz test będzie się kończył niepowodzeniem, aż nie
nie powinno mieć żadnych efektów ubocznych, tak więc nikt nie powinien
innego powodu.
_Layout.cshtml.
w poniższym przykładzie:
<li><a class="auto-register"
href="@Url.Action("Register",
"Members")">
@Html.LanguageString("Layout.Nav.Register")</a>
</li>
programistów.
Uwaga
Nie zapomnij wyczyścić pola wyszukiwania w panelu Solution
12.6.
Uwaga
najprostszą rzecz, która omija nasz bieżący wyjątek, tak więc nie
właściwości
Uwaga
Jeśli zastanawiasz się, czy umieszczanie literałów znakowych
one dosyć małe i wszystkie znajdują się w tej samej klasie, ale wciąż jest to
W miarę jak będziemy usuwać takie duplikaty, nasz kod będzie się stawał
się z tym uogólnianiem, tak więc teraz usuniemy jedynie duplikację w tej
jednej klasie. Jeśli później zobaczymy, że inne klasy również potrzebują tego
listingu 12.10.
Listing 12.10. Plik RegistrationPage.cs po usunięciu duplikacji
Uwaga
pracę nad tą metodą. Być może trzeba będzie do niej wrócić, aby przekazać
Category”.
Rysunek 12.5. Strona administratora pozwalająca na zmianę uprawnień
testowej SanityTests.
[TestInitialize]
public void TestInitialize()
{
var adminUser = MVCForum.LoginAsAdmin();
var adminPage =
adminUser.GoToAdminPage();
var permissions =
adminPage.GetPermissionsFor(TestDefaults.
StandardMembersRole);
permissions.AddToCategory(TestDefaults.Ex
ampleCategory,
PermissionTypes.CreateTopics);
adminUser.Logout();
}
Uwaga
W bibliotece MSTest metoda oznaczona atrybutem
Uwagi:
z systemu.
w metodzie GetPermissionsFor.
Moglibyśmy po prostu przekazać ciąg znaków „Standard Members” jako
D). Jeśli ktoś będzie musiał użyć tej metody później i będzie mógł
jednostkach, które istnieją w systemie, ale nie chcemy tworzyć dla nich
miejscem, które trzeba będzie zmienić. Jeśli nie użyjemy takiej klasy, to
tę metodę i zmieniłem klasę LoginPage w taki sposób, aby była ona klasą
pochodzącą FormPage.
z Zauważmy, że zarówno klasa
Uwaga
z tych poświadczeń.
https://github.com/arnonax/mvcforum/tree/TestInitializeCompleted/MVCFor
umAutomation.
Implementowanie metody CreateDiscussion
i analizowanie niepowodzenia
public Discussion
CreateDiscussion(Discussion.DiscussionBuilder
builder)
{
var newDiscussionButton =
WebDriver.FindElement(By.ClassName
("createtopicbutton"));
newDiscussionButton.Click();
WhenARegisteredUserStartsADiscussionOtherAnonymousUsersCanSee
pomóc nam zidentyfikować ten problem, jest zrzut ekranu strony w chwili
naszego zrzutu ekranu. Kliknięcie tego odnośnika otworzy nam zrzut ekranu
której pojawia się przycisk New Discussion (Nowa dyskusja). Jak pokazuje
powtórzony adres e-mail, który powinien być unikalny, tak jak nazwa
użytkownika.
MVCForumClient.RegisterNewUserAndLogin wiersz:
zamieniamy na:
Kończenie testu
Ten problem mamy już z głowy, a dodatkowo mamy teraz także prosty
https://github.com/arnonax/mvcforum/tree/FirstTestCompleted. Kolejne
https://github.com/arnonax/mvcforum/commits/FirstTestCompleted lub
w rozdziale 9).
Podczas tego procesu utworzyliśmy wiele klas i jeszcze więcej metod. Może
się to wydawać sporo jak na jeden test, ale wszystkie te klasy i metody
stabilny. Jest jeszcze kilka rzeczy do zrobienia, aby testy te mogły być
służyć nam przez długi czas, nie sprawiając przy tym problemów
z utworzonymi przeze mnie testami, ponieważ projekt ten nie miał jeszcze
żadnego testu. Ale zanim mogłem to zrobić, musiałem najpierw pobrać jego
przestał działać.
prosta.
Doświadczenie to zainspirowało mnie, aby skupić się w tym rozdziale na
MVCForum
z pliku wsadowego lub jakiegoś innego skryptu, który nie będzie częścią
automatycznie.
Jak możemy się dowiedzieć z tego komunikatu błędu i śladu stosu, nie
udało nam się znaleźć menu „My Tools” (Moje narzędzia), za pomocą
i patrzymy na zrzut ekranu, aby zobaczyć, czy menu to pojawia się, czy nie.
zalogować.
komunikatu o błędzie.
odtworzyć ten problem ręcznie lub też uruchomić test za pomocą debuggera
a jest nią zapisanie tej strony do pliku i otwarcie jej w trybie offline. Aby
return createLoggedInUser();
}
MVCForumClient.LoginAs
/// <returns>
/// Komunikat błędu wyświetlany na stronie
logowania lub null, jeśli nie
jest wyświetlany żaden błąd
/// </returns>
public string GetErrorMessageIfExists()
{
var errorMessageElement =
WebDriver.TryFindElement(
By.ClassName("validation-summary-errors"));
return errorMessageElement?.Text;
}
zwrócić null, jeśli nie pojawi się żaden błąd. Visual Studio wyświetla
TryFindElement.
Uwaga
Unikanie debugowania
możliwości debugowania i mogą nam one dać głęboki wgląd w to, co się
w debugowaniu, zaś testy migoczące (testy, które nie zawsze kończą się
opłaci.
Read Me i zobaczmy, czy coś się zmieniło. Rysunek 13.3 pokazuje nowy
(r=)76tn. Wygląda na to, że nie jest to po prostu nowe hasło domyślne, jak
wcześniej, ale raczej hasło wygenerowane losowo (jeśli uruchomisz ten kod
Rozwiązywanie problemu
Oczywiście nie chcemy używać hasła (r=)76tn, ponieważ zmieni się ono
przy następnym tworzeniu bazy danych. Zatem aby nasz test był poprawny
Me!
inne. Wiemy już, w jaki sposób pozyskać najnowszy temat z listy ostatnich
dole. Pobranie tematu z samego dołu może być kłopotliwe, jeśli tematy te
obejmują więcej niż jedną stronę, ale na razie nie będziemy rozważać takiej
GetAdminPassword.
[TestInitialize]
public void TestInitialize()
{
Uwaga
tej reguły.
Więcej problemów…
również i to.
(tj. zawiera on wszystko to, co powiązane jest z dyskusją, ale bez menu
głównego dla obiektu strony. Ten element główny powinien być użyty jako
konstruktor, jeśli nie uda nam się go znaleźć. Na listingu 13.5 pokazano
IWebElement _container.
Uwaga
konstrukcji.
Zabawa w detektywów
otwarta, tak więc komunikat nie kłamie. Musimy zatem kontynuować nasze
błąd). Mimo że przeglądanie śladu stosu lub kodu nie jest najprostszym
zostaje otwarta.
Thread.Sleep(10000);), bezpośrednio
sekund (za pomocą instrukcji
Uwaga
klawiszy Ctrl+F.
Jak widać, element ten został znaleziony i jest tylko jeden (o czym
podświetlony), ale nie samego tytułu Read Me, nie powoduje otwarcia
dyskusji.
Jedna rzecz nadal wygląda dziwnie. Metoda ta nie zmieniła się od czasu,
Patrząc na nowy zrzut ekranu (rysunek 13.5) oraz ślad stosu, możemy
z uprawnieniami.
zająć trochę czasu, tak więc zapiszemy sobie ten pomysł na karteczce
razie możemy zrobić dwa dodatkowe zrzuty ekranu: jeden przed dodaniem
rysunku 13.6.
Widzimy, że trzecie uprawnienie jest zaznaczone, ale co to? Nie jest już
Przechwytywanie ekranu
wtedy takie rzeczy jak komunikaty błędów – nawet z innych aplikacji lub
Aby zaoszczędzić miejsce na dysku, możemy też usunąć takie wideo, gdy
nam będzie ustalić, który przycisk został w danej chwili kliknięty. Zatem na
podstawie samego takiego filmu może nam być trudno zrozumieć, co tak
zakończeniu testu, usuwając ewentualnie plik wideo, jeśli test zakończył się
inny kod w projekcie testu nie powinien być zmieniany, aby można było
us/visualstudio/test/configureunit-tests-by-using-a-dot-runsettings-file.
Rejestrowanie
jak wypisywanie tekstu na standardowe wyjście konsoli, ale może być ono
zapisać w dzienniku.
docelową może być wyjście konsoli, plik, baza danych itd. Możemy również
interesują.
Rejestrowanie zagnieżdżone
znacznie trudniej będzie nam zobaczyć całość i znaleźć to, czego szukamy.
Adding a Category
Opening Admin page
Clicking on 'My Tools'
Clicking on 'Admin'
[Done: Opening Admin Page]
Opening Categories page
Clicking on 'Categories'
[Done: Opening Categories page]
Creating new category
Clicking 'Create New'
Typing 'Test category' in 'Category Name'
Clicking 'Create'
[Done: Creating new category]
Click 'Main Site'
[Done: Adding a Category]
Uwaga
reference/keywords/using-statement.
Rejestrowanie wizualne
możemy skorzystać:
informacje, które mogą być dla nas bardzo pomocne w przypadku, gdy
dany element nie został znaleziony na stronie (tj. gdy zgłaszany jest
Notepad++).
z komunikacją.
bardziej spójny.
dzienniki możemy często uzyskać z tej części serwera sieci Web, która
udostępnia aplikację taką jak Microsoft Internet Information Services
(IIS).
wykonywania testu różnica ta powinna być dosyć stała, tak więc jeśli
prawdziwy problem i sprawdzić, czy komunikat ten już się nie pojawia.
temat:
SanityTests.GetAdminPassword
Zastąpiliśmy domyślne renderowanie komunikatów ExtentReports, aby
IWebElement.Location
(za pomocą właściwości
prawda?
rozmiarze.
Rysunek 13.7. Wynik zagnieżdżonego rejestratora wizualnego
może zająć sporo czasu i być dosyć frustrujące. Poniżej znajduje się kilka
efektywnej obsługi.
pomyślnie (lub działa poprawnie), tak więc test ten kończy się sukcesem na
jego maszynie. Problemy mogą się pojawić, gdy kolejny deweloper próbuje
uruchomić ten test lub gdy test wykonywany jest na maszynie kompilacji.
dany problem na innej lub nawet naszej maszynie, aby kontynuować analizę.
Pierwszą rzeczą, którą należy zweryfikować, jest to, czy wersje testu
i testowanego systemu są takie same na obu maszynach. Jeśli nie są, to nie
nadal tak jest. Jeśli test zakończy się sukcesem, to jeszcze możemy zbadać
gdy test nadal kończy się niepowodzeniem, różnica może tkwić w wersjach
testowanego systemu.
zmianę jednej strony tak, aby pasowała do drugiej. Jeśli wyniki się od siebie
kluczowej różnicy i powtarzamy ten proces. Gdy zmieniona przez nas strona
niepowodzeniem. Jeśli przy użyciu tej drugiej bazy danych test zakończy się
związany z bazą danych, więc musimy poszukać innej różnicy. Jeśli test
przyczyną niepowodzenia testu jest nowa wersja schematu, przy czym nadal
Podczas przechodzenia przez ten proces ważne jest to, aby komunikat
dowiedzieć się, czy ten nowy błąd miał miejsce przed czy po wystąpieniu
może być ręczne napisanie pliku dziennika (za pomocą edytora tekstowego)
wyłącznie metodę prób i błędów. Dziennik ten może być dla nas pomocny
i innymi próbami.
różnicą. Aby upewnić się, że faktycznie tak jest, możemy – jeśli jest to
różnicy.
Zawężanie kodu
zakomentować wiersze kodu, które wydają się nie być związane z danym
wykonywalne testu (pliki DLL, JAR itd.) na inną maszynę. Czasem warto
a wtedy już łatwo nam będzie zrozumieć, co tak naprawdę się dzieje.
Badanie testów wpływających na inne testy
Czasem jest tak, że gdy uruchamiamy testy osobno lub jako część
niewielkiej grupy testów, to zawsze kończą się one sukcesem, ale gdy
i sprawdzić, czy dostaniemy taki sam wynik. Jeśli tak się stanie, to łatwo
Jeśli jednak nie mamy pojęcia, co może być przyczyną tego problemu,
możemy ponownie zagrać w grę „lew na pustyni”, ale tym razem w nieco
nowy zestaw testów, który zawiera wyłącznie testy od 1 do 14, a także test
28. Jeśli test 28 zakończy się teraz sukcesem, będzie to oznaczać, że testem
problemu, a które nie, więc będziemy można jeszcze bardziej zmniejszyć ten
zakres poszukiwań.
dany problem, czy po prostu mieliśmy tym razem szczęście. Istnieje jednak
stosowania.
poprawnie. Jeśli test kończący się sukcesem raz na trzy próby uznawany
równolegle.
wady:
żadnego problemu w tym, aby ustalić jakiś próg, powyżej którego czas
100%, tym szybciej będzie rosnąć czas oczekiwania. Oznacza to, że jeśli
przykładowej operacji
Gdy czekamy przez z góry określony czas, to gdy on już upłynie, zwykle
nie wiemy, czy operacja ta naprawdę się zakończyła, czy nie. Jeśli tego
być łatwe.
z serwera. Przykładowo
IWebDriver.Manager().Timeouts().ImplicitWait.
Wartość ta ma wpływ na to, jak długo Selenium będzie czekać na
var button =
webDriver.FindElement(By.Id("approveButton"));
wait.Until(ExpectedConditions.ElementToBeClickab
le(button));
button.Click();
Uwaga
przypadków test nie będzie czekał aż tak długo, a jedynie wtedy, gdy
systemie albo błąd w teście). Wartość limitu czasu powinna być na tyle duża,
aby można było uniknąć niepotrzebnych niepowodzeń testów, ale też nie na
z oczekiwania na wynik.
minut…
niewłaściwej izolacji lub jakiegoś innego powodu. Tym samym nie możemy
badanie to nadal trwa zbyt długo, to trzeba jakoś oznaczyć te testy lub je
i stopniowo starać się usunąć kod lub operacje, które wydają się nie mieć
że operacja usunięta przez nas z pętli jako ostatnia jest związana z tym
składowych. Jeśli operacji nie da się już dalej podzielić, wówczas z tak
Podsumowanie
ważne jest, aby skrzętnie zbadać każdy problem i znaleźć jego główną
i precyzyjne, tak aby można było szybko reagować. W tym celu wszelkie
informacje, które mogą pomóc nam zbadać i zrozumieć, co tak naprawdę się
pierwszy test:
wyjątek NotImplementedException).
Uruchamiamy test, a następnie implementujemy pierwszą metodę, która
się sukcesem.
klasa czy metoda, to kolejne testy mogą już zawierać niektóre z nich.
zmian.
2. Klasa lub metoda nie istnieje. Musimy utworzyć ją dokładnie tak, jak
3. Istnieje podobna klasa lub metoda, ale nie jest ona dokładnie taka, jakiej
parametru.
Oczywiście pierwsza z tych opcji nie jest zbyt przydatna, jeśli zależy
jako Wujek Bob) twierdzi, że prawie żadna metoda nie powinna mieć
więcej niż jeden lub dwa parametry. Choć nie mówi on tego
powinny być używane tylko wtedy, gdy dana wartość musi być
zamiast tworzenia jednej dużej metody, która musi brać pod uwagę
jednak pewien dylemat: z jednej strony, jeśli dodamy testy dla jakiejś
obierają mniej więcej taki sam kierunek co nasz pierwszy test, ale
i dodamy testy dla całkiem innej funkcji (lub nawet całkowicie innego
infrastrukturę. Nie ma w tym nic złego, ale zwykle lepiej bardziej się skupić
kolejnego.
w pierwszym teście.
przypadku większość testów będzie do siebie dosyć podobna i będą one się
kategorii. Ta druga kategoria powinna być pusta. Listing 14.1 zawiera plan
wierszach kodu.
zmiennych.
ponieważ w tym teście nie interesuje nas tak bardzo, za pomocą którego
[TestMethod]
public void DiscussionsCanBeFilteredByCategory()
{
var adminConsole = MVCForum.AdminConsole;
var categoryA =
adminConsole.CreateCategory();
var categoryB =
adminConsole.CreateCategory();
var user =
MVCForum.RegisterNewUserAndLogin();
var discussion =
user.CreateDiscussion(DiscussionWith.
Category(categoryA));
var categoryView =
MVCForum.Categories.Select(categoryA);
Assert.AreEqual(1,
categoryView.Discussions.Count,
$"1 discussion is expected in categoryA
({categoryA.Name})");
Assert.AreEqual(discussion,
categoryView.Discussions.
Single(), $"The single discussion in
categoryA ({categoryA.
Name}) is expected to be the same category
that we’ve created
('{discussion.Title}");
categoryView =
MVCForum.Categories.Select(categoryB);
Assert.AreEqual(0,
categoryView.Discussions.Count,
$"No discussions expected in categoryB
({categoryB.Name}");
}
Listing 14.3. Szkielet metody DiscussionsCanBeFilteredByCategory
budowniczego.
Uwaga
Dalsze zasady już znamy: tworzymy nowe klasy i metody, aż kod się
skompilować kod:
Uwaga
public DiscussionBuilder
Discussion.Category(Category category)
Uwaga
Assert.
Gdy nasz test już się skompiluje i zostanie uruchomiony, wówczas pierwszy
AddCreateTopicPermissionToStandardMembers. Pogrubione
MVCForum.AdminConsole.
Uwaga
AddCreateTopicPermissionToStandardMembers,
aby oddzielić go od inicjalizacji samego rejestratora.
private void
AddCreateTopicPermissionToStandardMembers()
{
using (Logger.StartSection(
"Adding 'Create Topic' permission to Standard
members"))
{
var adminPassword = GetAdminPassword();
var adminUser =
MVCForum.LoginAsAdmin(adminPassword);
var adminConsole =
adminUser.GoToAdminConsole();
var permissions =
adminConsole.GetPermissionsFor(
TestDefaults.StandardMembers);
permissions.AddToCategory(TestDefaults.E
xampleCategory,
PermissionTypes.CreateTopics);
adminUser.Logout();
}
}
niż przedtem, ale za to mniejsze zło! Listing 14.5 pokazuje te zmiany po ich
[TestMethod]
public void DiscussionsCanBeFilteredByCategory()
{
Category categoryA, categoryB;
using (var adminConsole =
MVCForum.OpenAdminConsole())
{
categoryA =
adminConsole.CreateCategory();
categoryB =
adminConsole.CreateCategory();
}
var user =
MVCForum.RegisterNewUserAndLogin();
...
}
metody AddCreateTopicPermissionToStandardMembers. Po
usunięciu duplikacji ustawimy ją z powrotem na private wewnątrz klasy
MVCForumClient), i gotowe! Metoda została przeniesiona do klasy
MVCForumClient.OpenAdminConsole
public AdminConsole(
IWebDriver webDriver, LoggedInAdmin loggedInAdmin)
{
_webDriver = webDriver;
_loggedInAdmin = loggedInAdmin;
}
zawiera metodę
AddCreateTopicPermissionToStandardMembers po usunięciu
duplikacji.
Listing 14.8. Metoda AddCreateTopicPermissionToStandardMembers po
usunięciu duplikacji
(MVCForumClient).
MVCForumClient.
private readonly Lazy<string> _adminPassword;
public MVCForumClient(TestDefaults testDefaults)
{
_adminPassword = new Lazy<string>
(GetAdminPassword);
...
}
metody, która już istnieje, lub metody, która w ogóle jeszcze nie istnieje,
bądź mamy już podobną metodę, lecz nie taką, jakiej potrzebujemy, więc
musimy zmodyfikować istniejący kod, aby osiągnąć nasz nowy cel i usunąć
duplikację. Listing 14.10 pokazuje, w jaki sposób metoda
istniejące metody
jednak nie do końca. Sposób, w jaki jest ona zaimplementowana, rodzi dwa
problemy:
CategoryView. Nie wygląda to jednak zbyt dobrze – nie jest wcale tak,
że nie musimy nigdy aktywować widoku kategorii, ale nie wydaje się, aby
miejscu.
DiscussionsList.
method
MVCForumAutomation.SanityTests.DiscussionsCanBeFilteredByCate
element nie jest już dostępny w modelu DOM. Jeśli jednak spojrzymy na
kod testu i ślad stosu, wszystko będzie jasne: próbujemy odczytać tytuł
Mimo że tytuł dyskusji możemy zobaczyć przy użyciu tej listy, to jednak
sposób wyodrębniania tej wartości z modelu DOM jest inny. Tak czy
pierwszy test również zakończy się pomyślnie. Na szczęście tak właśnie się
dzieje.
w projektowaniu i programowaniu.
Gdy test jest już ukończony, jest to dobry moment na usprawnienie rzeczy,
ostatniego testu – ale nie była ona wystarczająco istotna, aby przerwać ten
dodamy prefiks zawierający rodzaj danej jednostki, to nasze życie stanie się
dużo prostsze.
utworzone przez nas klasy mają postać jednej długiej listy 28 plików
chociaż jej część, to znalezienie jej nie będzie dla nas stanowić problemu
Ctrl+T, aby szybko znaleźć dowolny symbol). Jeśli jednak nie wiemy
klasy nie pasują dobrze do żadnej z tych kategorii i nie ma z tym żadnego
Teraz testy świetnie działają na naszej maszynie, ale aby uzyskać z nich
prostsze.
tak więc obsługa innego środowiska nie powinna stanowić problemu. Jeśli
zobaczymy, że jego serwer sieci Web zamiast portu 8080, jak w naszym
Ponieważ zależy nam na tym, aby testy były jak najbardziej spójne
domyślnego również mogą być przydatne, jeśli system nie wczytuje się
od zera przy każdym uruchomieniu. Jednak posiadanie identyfikatorów
tylko przez oprogramowanie. Oznacza to, że powinny być one tak łatwe
elementów w pliku XML, z którym powiązany jest plik XSD. Plik XSD
sprawdzamy, czy plik ten istnieje, a jeśli nie istnieje, to dajemy jasny
przeglądarkach, tak więc istotne jest, aby uruchamiać nasze testy w wielu
z konfiguracją
w poprzednim zatwierdzeniu.
Uwaga
dowiedzieć się, czy wprowadzone przez nas poprawki niczego nie popsuły.
wyłącznie okazjonalnie i ręcznie, nie zajmuje to zbyt wiele czasu, ale jeśli
inni ludzie używają tych testów i nie stosują tej praktyki, mogą potencjalnie
Istnieje kilka opcji rozwiązania tego problemu, ale jak zwykle każda z nich
jednak dokonać samodzielnie. Oto kilka takich opcji, które można wziąć
pod uwagę:
Oczyszczanie
powodu nie jest możliwe, możemy oczyścić te jednostki, aby uchronić się
naprawdę nie wie, która funkcja wymaga których danych. Z tego powodu
jednostki.
podejścia, jest to, aby nie usuwać jednostek testów, które są aktualnie
być w użyciu, np. przez ostatnie 24 godziny. Jeśli nie zawierają one takiego
jednostki oraz czas jej utworzenia. Za każdym razem, gdy test tworzy jakąś
Mechanizm taki oczyszcza każdą jednostkę utworzoną przez test, gdy test
Pewną wadą tego podejścia jest jednak to, że gdy wykonywanie testu
dwóch podejść.
Uwaga
i ograniczone zasoby.
Poprawienie wydajności
od 30 do 60 sekund. Nie jest to dużo jak na test kompleksowy, ale nadal nie
jest to dość szybko. Biorąc pod uwagę, że takich testów będziemy mieć
rozważyć, czy jest to tego warte, czy też nie, ale jest to jakaś opcja możliwa
szczegółowo w rozdziale 6.
nasz kod powinien być łatwy w utrzymaniu i powinno nam być łatwo
pokryć w całości jakąś nową funkcję, które nie była wcześniej pokryta
cała logika metody testowej jest duplikacją, zaś sposobem na jej usunięcie
tabela może mieć formę atrybutów (adnotacji w Javie) nad metodą testową,
lub zewnętrznego źródła danych, takiego jak plik CSV, plik Excela, tabela
bazy danych itd. Gdy test zostaje uruchomiony, biblioteka traktuje go jak
szereg testów i uruchamia metodę testową raz dla każdego wiersza w tabeli.
testowym.
hasło, system wskazuje, czy jest ono poprawne, czy nie, a jeśli jest, to
pokazuje siłę tego hasła. Zatem system dla każdego podanego hasła
wskazuje, czy jest ono niepoprawne (Invalid), słabe (Poor), średnie
[TestMethod]
[DataRow("", PasswordStrength.Invalid)]
[DataRow("abc", PasswordStrength.Invalid)]
[DataRow("abcdefg1", PasswordStrength.Poor)]
[DataRow("abc123@$#", PasswordStrength.Medium)]
[DataRow("$g62D*&a244dfle*)]",
PasswordStrength.Good)]
public void PasswordValidation(string password,
PasswordStrength expectedInidication)
{
registrationPage.Password = password;
Assert.AreEqual(expectedInidication,
registrationPage.
PasswordStrength);
}
poprawne, czy nie. Mówiąc bardziej ogólnie, powodem, dla którego jest
Podsumowanie
testów.
Ponadto, gdy mamy już ukończony jeden lub kilka testów, możemy
Gdy mamy już przynajmniej jeden test i jesteśmy w stanie uruchamiać testy
testy automatyczne.
Uwaga
sposób nikt nie może posłużyć się niesławnym powiedzeniem „ale na moim
wdrożyć takiego serwera na wczesnym etapie. Jeszcze kilka lat temu nie
było to wcale takie proste i także dziś zdarzają się przypadki, w których
zespoły nie mają jeszcze serwera kompilacji lub nie mają odpowiedniej
Jednak ludzie popełniają błędy, a gdy znajdują się pod presją, często idą
zauważalne, gdy rozmiar zespołu przekracza dwie lub trzy osoby, a czas
w użyciu, a jeśli musimy nauczyć się nimi posługiwać, możemy w tym celu
skompilowaniu projektu.
zależności od tego, jak długo nasz zespół jest w stanie czekać na informacje
operacji ewidencjonowania kodu. Jednak gdy proces ten trwa dłużej lub
ale również wtedy, gdy jakaś szybka lub ryzykowna zmiana musi zostać
Kompilacje nocne
błędy deweloperom.
rzadko patrzą na same rezultaty testów, a zamiast tego skupiają się głównie
kompilacji, ale zaraz po tym, jak kompilacja ciągłej integracji (która nie
prawdopodobnie również nie będą starali się ich badać, ponieważ z ich
ewidencjonować kodu, który się nie kompiluje, ale nic poza tym.
Jeśli zostanie zaimplementowana tylko ta pierwsza część kompilacji CI,
z niezawodnością i zaufaniem.
stanowić duży problem, często taka aktualizacja jest robiona ręcznie. Jeśli
schemat bazy danych zmienia się dużo rzadziej niż kod i musimy poradzić
i wdrożonej aplikacji:
produkcyjnym).
Jeśli mamy już kompilację CI, która jest regularnie używana, ale nie
itd.
Czasami nawet to nie jest konieczne, jeśli nasz kod testu znajduje się
środowisku.
Uwaga
testowania. Jeśli nie jesteśmy pewni, czy nasz system kompilacji obsługuje
Choć zacieranie tych różnic może być dosyć nużącym zadaniem, to zwykle
w dzienniku.
pozostałe testy.
Jeśli wiemy, że cały nasz zestaw testów jest stabilny (lub po prostu nie
kompilację nocną lub zająć się ich lokalnymi problemami, zanim dodamy je
tej pory, jest zadaniem technicznym. Jednak proces ten sam w sobie nie
powinniśmy dążyć, przy czym może to być dosyć długa podróż. Może być
tak, że nasz cel wciąż leży poza naszym zasięgiem i jest dużo bardziej
skromny, ale tak czy inaczej, każdy cel, który zostaje osiągnięty, stanowi
faktyczny cel jest inny. Ważne jest to, że wiemy, jakie korzyści możemy
Zmiana kultury może wydawać się wielką sprawą, która leży poza
liderem. Ale różne osoby mogą być liderami w jednych aspektach lub
zwykle potrzebny jest tylko jeden lider. Nie ma żadnego powodu, dla
którego to my nie moglibyśmy być nim być! Nie musimy być menedżerami
ten temat bardziej niż im. Jeśli będziemy to kontynuować, to już niedługo
na temat automatyzacji testów inni, nasz wpływ będzie stale rosnąć, więc
coraz więcej osób będzie nas słuchać. Prawdopodobnie nie stanie się to
z dnia na dzień i może upłynąć bardzo długi czas, zanim będziemy mogli
rozczarować, ale tak naprawdę naszym celem jest samo dążenie do niego –
tym etapie będziemy już dążyć do czegoś nowego. Przygotujmy się więc na
długą podróż, która mimo wszystko powinna być dla nas niezwykle
satysfakcjonująca!
Przekonywać i wpływać na inne osoby można na wiele sposobów, które
mu potencjalną wartość zmiany oraz jak mały niesie ona ze sobą koszt,
jakości może nie dostrzec wartości, jaką deweloperzy mogą zyskać dzięki
i poprosi go, aby pozwolił nam im pomóc. Jeśli to konieczne, ich menedżer
Rozbieżność oczekiwań
projektu.
zbyt techniczny, aby był on zrozumiały dla tych menedżerów. Nawet jeśli
to nadal nie jest to coś, co nasz menedżer będzie chciał wykorzystywać dla
przekazuje te informacje.
lub załagodzić ten problem. Znane błędy należy w jakiś sposób odróżnić od
więcej czasu lub pomocy od innych osób), aby ułatwić sobie badanie tego
procesach i kulturze. Taki raport będzie dużo bardziej cenny dla naszego
scenariusz działa, czy nie, ani czy niepowodzenie powodowane jest przez
czas. Z tego powodu testy muszą być zawsze stabilne. Na potrzeby naszej
Choć nie jest to pożądane, zbyt często zdarzają się sytuacje, w których
w czasie).
tych, które są już dosyć stabilne. Nawet jeśli większość testów jest
zacznijmy od tych, które aktualnie piszemy, a gdy tylko zaczną one działać,
nawet jeśli lista będzie ona bardzo krótka. Każdego ranka, zamiast badać
niepowodzenia wszystkich testów, skupmy się na testach uwzględnionych
na tej liście. Ponieważ lista zawiera testy, które są dość stabilne, powinny
one zwykle kończyć się sukcesem, tak więc czas poświęcony na ich
w poprzednim temacie. Gdy już wszystkie testy z tej listy będą kończyć się
kilka testów, które wydają nam się dosyć stabilne. Możemy również wybrać
z wprowadzonych przez nas poprawek dla testów z tej listy, czy też
stabilne.
trudno nam będzie ustabilizować, to będą one raczej stanowić wyjątek niż
zdamy sobie sprawę, że ich wartość nie jest tak jasna, jak sądziliśmy.
na badanie i naprawianie błędów nie będzie już tak długi, zaś dostrzegana
z automatyzacji testów.
lub opisów są dla nas zrozumiałe (lub dla ekspertów z danej dziedziny
lub architekturą, a cel testów nie jest dla nas zrozumiały, to możemy
ilość czasu. Jeśli można je łatwo naprawić, to zróbmy to, a jeśli dodatkowo
możemy również zmienić nazwę lub opis metody testowej, aby lepiej
opisywała jej przeznaczenie, to jeszcze lepiej. Jeśli uważamy, że test jest
Jeśli jednak w starej infrastrukturze jest jakiś użyteczny kod, który możemy
nowego systemu.
różnych symptomów:
zarząd.
2. Błędy, których priorytet nie jest wystarczająco wysoki, aby były one
automatyzacji.
priorytetu.
szczegółowo testować swoich zmian i nowych funkcji, lub pisać testów dla
przycisku, poczują się oni bardziej pewnie, że ich zmiany nie wyrządziły
żadnej istotnej szkody. Mimo wszystko deweloperzy nie lubią, gdy w ich
kodzie znajdowane są błędy, ponieważ w ten sposób mają oni więcej pracy
pokazać im, w jaki sposób mogą oni uruchamiać jeden, kilka lub wszystkie
testy (w zależności od tego, ile czasu zajmuje taka operacja). Istnieje duża
z deweloperów napotka błąd i wezwie nas, aby mu w tym pomóc. Gdy tak
się stanie, pokażmy mu, w jaki sposób możemy zbadać takie
błąd i upewnijmy się, że test kończy się sukcesem. Jeśli przyczyną była
większości przypadków nie powinno tak być, jeśli trzymaliśmy się zasady
Zakładając, że deweloper ten wie już, jak należy uruchamiać testy, i że jest
Wreszcie ktoś już zasugeruje, aby dodać testy (lub ich podzbiór) do
kompilacji CI, żeby uchronić się przed powtórnym pojawianiem się tego
Uwaga
w tym trochę lepsi, staje się dla nich oczywiste, że tworzenie tych
rodzaje zadań, czy też każdy z nich wykonuje swoją pracę. Nie
nie wykonuje się zbyt długo, gdyż w przeciwnym wypadku nie będą oni
testowania nie powinien trwać dłużej niż kilka minut czy nawet sekund, ale
który pozwala mu zająć się czymś nowym. Jest tak, ponieważ gdy
kompilacja zakończy się niepowodzeniem, będzie on musiał dokonać
o szerszym zakresie.
Ulepszanie izolacji
zaś ilość danych może mieć wpływ na wydajność zapytań, które aplikacja
swoją własną małą bazę danych, to usuwamy w ten sposób wąskie gardło
zwiększa wydajność.
użytkownika zwykle zajmuje długi czas i może sprawić, że testy będą mniej
wielu testów równolegle powinno być już bardzo proste. To, czy do
dobrze w tę technologię lub też nie mamy wystarczającej wiedzy lub czasu,
aby nauczyć się z niej korzystać, to nie powinno nas wstrzymywać przed
rzędu wielkości.
zakończył się sukcesem, czy nie. Oczywiście cały ten proces można łatwo
Jego wadą jest jednak to, że proces pracy staje się nieco bardziej
swoje zmiany, czy też nie. Nie mówiąc już o tym, że niepowodzenie
mniejszy zakres testowania, tym szybsze testy. Dlatego, biorąc pod uwagę
Oczywiście im mniejszy staje się zakres, tym mniejszą pracę wykonują one
zakresu.
testów musi jedynie testować jeden komponent, zaś tylko kilka testów
w potoku CI.
fakt, że jakiś system złożony jest z wielu usług, nie gwarantuje, że usługi te
zaoszczędzić.
Jedną z największych zalet automatyzacji testów jest to, że może być ona
w stabilizacji.
Podsumowanie
dostarczyć, testy nie powinny wykonywać się zbyt długo. W rozdziale tym
część bycia zwinnym, ale to zbyt mało. Aby zespół był zwinny, musi on
być w stanie szybko reagować na opinie klientów i robić to przez cały czas
zwinność.
Uwaga
osiągnąć.
Dług techniczny
odkładać naprawę tych skrótów, tym więcej będziemy mieć pracy. Możemy
więcej czasu i większego wysiłku. W tym sensie pisanie kodu, którego nie
testowanie zajmie nam więcej czasu, a jeśli nie zrobimy tego wystarczająco
spowalniał zespół, więc nie będzie on już tak zwinny jak do tej pory
Aby zespół mógł pozostać zwinny przez długi czas, powinien unikać długu
a sztuka polega na tym, żeby to zrobić w taki sposób, aby każda z nich
specyfikacji dla jakiejś funkcji jako całości (możemy o tym myśleć jak
oczyszczanie.
zobaczymy, w jaki sposób podejście ATDD pozwala nam się z nimi uporać.
Proces
każdego kroku:
3. Piszemy kod aplikacji, aby nowe testy kończyły się sukcesem. Ponadto
sukcesem.
Stories, autorzy Gojko Adzic i David Evans mówią o tym w ten sposób:
wielokrotnego dostarczania.
spełnienie dostarcza tym klientom największą wartość (za którą będą nam
Jako [rola]
Aby móc [rozwiązać problem, zrealizować potrzebę
lub dostarczyć większą wartość]
Chcę [proponowane rozwiązanie]
lub jakimś podobnym wariancie. Gojko i David sugerują nawet, że ten, kto
Tworzenie rozwiązania
Gdy potrzeba jest już zrozumiała i nadano jej właściwy priorytet, zespół
problem polega na tym, w jaki sposób spełnić potrzebę klienta, a nie jak
Zaleca się, aby uczestnikami tej konwersacji były osoby, którzy będą
użytkownika.
w taki sam sposób, może się zdarzyć, że pomijają oni jakiś istotny
tych problemów.
Jeśli testy automatyczne i kod aplikacji piszą inne osoby, to tak naprawdę
testy automatyczne nie muszą być pisane wcześniej, gdyż można to robić
w późniejszym czasie.
Jeśli ten sam deweloper pisze kod aplikacji i testy automatyczne, lub też
uzupełniający), wówczas zaleca się, aby testy pisane były jako pierwsze.
Jeśli istnieje więcej niż jeden test, to zespół może zdecydować, czy
wszystkie testy, bądź też czy przed napisaniem każdego kolejnego testu
przy czym pisanie kodu również może ujawnić pewne ograniczenia, które
programming)
aby partnerzy z różnych par zmieniali się ze sobą, aby zapewnić lepszą
cały kod. Nie mówiąc już o tym, że transfer wiedzy między tymi
wzajemnie się uzupełniają, ale gdy realizowane przez nich zadanie jest
niektóre osoby czują się lepiej programując w parze, podczas gdy inne
napisanie kodu, który się kompiluje, nie powinno być problemem, ale
zamiast decydować o tych szczegółach w czasie, gdy (my lub ktoś inny)
tym prostym przykładzie tak nie jest, ale jeśli obliczenia będą nieco
jeśli tylko robi się to z głową (w tym przypadku stała jest tylko dokładna
niż jeden krok, który nie może działać, dopóki kod aplikacji nie zostanie
naszą pracę w taki sposób, aby najpierw zaczął działać ten pierwszy
zmian, ale dla tego problemu nie będzie to dobre metodyczne podejście.
Uwaga
deweloperami.
tego zadania jest bardzo prosty: sprawić, że nowe testy będą kończyć się
powinno to być naprawdę proste. Jeśli pokrycie testów nie jest tak wysokie,
psucia przy tym istniejących testów” trzeba się również postarać, aby nie
popsuć niczego, co już działa, nawet jeśli nie mamy dla tych rzeczy
żadnych testów.
Ponieważ testy zawsze są jedynie konkretnymi przykładami, a nie samą
regułą, nie można za bardzo brać sobie tej rady do serca i sprawić, że
wartości, jakie są w tych testach oczekiwane. Jasne jest, że nie należy tego
pokrywane testami jednostkowymi, tak więc zaleca się pisanie dla nich
kod został napisany, przy założeniu, że wszystkie testy nadal kończą się
projektowe mogą nie być już poprawne, więc projekt musi się zmienić, aby
projektu, to refaktoryzacja może nie być dla nas zbyt łatwa, ponieważ nie
będzie działał poprawnie) może potrwać kilka dni lub nawet tygodni.
ktoś inny spojrzy na ten kod, będzie można zrozumieć, dlaczego powstały
z refaktoryzacją, jeśli nasz kod nie kompiluje się lub niektóre testy są
Jeśli oczekujemy, że testy zakończą się sukcesem, a tak się nie stanie,
użytkownika. Tak czy inaczej, jeśli tylko jesteśmy w stanie naprawić ten
tym kątem).
z dużych zalet metodyk ATDD i TDD jest to, że pozwalają nam one
jest dużo mniejsza, a nawet jeśli błąd taki zostanie znaleziony, to całkiem
w stanie zmierzyć testy automatyczne, zaleca się, aby tester manualny lub
nieczytelny rozmiar lub kolor fontu, przycięty tekst itp.). Jeśli są jakieś
testy regresji, które nie nadają się do automatyzacji, a mają jakiś związek
systemu. Zaletą tego rodzaju dokumentacji jest to, że jest ona zawsze
zaktualizowany.
klientów.
automatycznymi jest samo w sobie bardzo cenne, ale nadal mogą się tu
wykorzystują język o nieco luźniejszym stylu, ale sama ich koncepcja jest
(łącznie z SpecFlow, czyli wersją dla platformy .NET), testy oraz zdania,
również inne konstrukcje, ale jego główna koncepcja jest właśnie taka.
Feature: ATM
As a bank manager
In order to increase my income from
commissions
I want to allow my customers to withdraw
cash from ATMs
Scenario: Cash withdrawal charges commission
Given the commission is $1
When I withdraw $50
Then the charged commission should be $1
jeśli test zostanie napisany w całości w kodzie, to i tak może się zdarzyć, że
metoda robi (w dobrym, czystym kodzie nie powinno to mieć miejsca, ale
mimo wszystko może się to zdarzyć). Jeśli zatem chcemy pójść na całość,
Gdy z kolei chcemy, aby nasze testy były tak czytelne, jak to tylko
mniej czytelne.
MicroFocus Quality Center itd., zaś ich identyfikatory mogą być podawane
kryteriów akceptacji. Na początku (a być może jeszcze przez długi czas) nie
automatyzacji testów.
w projekcie, ale nie jest ona jeszcze wystarczająco dojrzała i stabilna, aby
automatyzacji nie później niż przy następnym sprincie (iteracji) może być
z myślą o testowaniu.
szybciej. Gdy błąd zostanie już usunięty i test zakończy się sukcesem,
i taki nowy test należy dodać do kompilacji nocnej lub kompilacji CI.
Podsumowanie
wartości.
Głównym problemem związanym z tą metodyką jest to, że wymaga ona
w których zaleca się pisanie testów przed pisaniem kodu. Jednak ATDD
(lub BDD) zwykle bardziej nadaje się dla dużych zakresów testowania
postaci pojedynczej klasy lub nawet metody), a tym samym testuje więcej
takich testów lub mają z nimi problem, niż takich, którzy robią to
do podejścia TDD toczą się żarliwe dyskusje na temat tego, jaki jest
prawdopodobnie nigdy się nie kończy. Jeśli chodzi o mnie, to od czasu, gdy
Ćwiczenia kata
Kata jest japońskim słowem zapożyczonym z domeny sztuk walki,
dosyć szybko nauczyć się czytać wszystkie nuty i grać każdą z nich na
nie pozwoli nam wcale zagrać muzyki Chopina, nie mówiąc już
technicznej.
jest tak naprawdę bardzo prostą technologią, ale mimo to jest niezwykle
i xUnit.NET dla platformy .NET, JUnit i TestNg dla Javy, PyTest dla
takie same.
dowolną z nich, bądź też sekwencyjnie każdą z nich lub dowolny ich
podzbiór, tak jak sobie tego życzymy. Idea polega na tym, że każdy test
wskazanie takiej metody, ale sama idea jest zawsze taka sama. Dzięki temu
w ten sposób, czy w danej klasie należy poszukiwać metod testowych, czy
pokazuje stan każdego z nich w postaci sukcesu lub porażki. Sposób, w jaki
określa on, czy test zakończył się sukcesem czy niepowodzeniem jest
bardzo prosty: jeśli test ukończył się bez zgłaszania żadnego wyjątku, test
Asercje
w rozdziale 11.
Klasa Assert w bibliotece MSTest, jak zresztą większość z jej
kodu pomiędzy tymi metodami. Ponieważ jednak wiele testów musi często
zainicjalizować tylko raz, bez względu na to, czy uruchamiamy tylko jeden
test, wiele testów, czy wszystkie testy w danym projekcie. To samo dotyczy
Uwaga
mechanizmu.
Uwagi:
metody AssembyCleanup.
2. Jak widać, metody ClassC.ClassInitialize oraz
pomyślnie, jeśli nie zgłaszają one żadnego wyjątku, lub jako zakończone
sprawa.
i zweryfikować ich rezultat. W tym celu nasz projekt testu musi odwoływać
często jest tak, że wiele testów w tej samej klasie testowej musi utworzyć
na początku testu instancję obiektu tej samej klasy, taka instancja jest
ale nie zaleca się tego robić, ponieważ są one uznawane za szczegóły
[TestClass]
public class CalculatorEngineTests
{
private CalculatorEngine _calculator;
[TestInitialize]
public void TestInitialize()
{
// Aranżacja
_calculator = new CalculatorEngine();
}
[TestMethod]
public void
CalculatorCanAcceptMultipleDigitNumbers()
{
// Akcja
_calculator.ProcessDigit(Digit.Eight);
_calculator.ProcessDigit(Digit.Five);
_calculator.ProcessDigit(Digit.Two);
// Asercja
Assert.AreEqual(852,
_calculator.DisplayedValue);
}
[TestMethod]
public void
CalculatorCanAcceptDecimalFraction()
{
// Akcja
_calculator.ProcessDigit(Digit.Four);
_calculator.ProcessDecimalPoint();
_calculator.ProcessDigit(Digit.Seven);
// Asercja
Assert.AreEqual(4.7,
_calculator.DisplayedValue);
}
[TestMethod]
public void CalculatorCanMultiplyNumbers()
{
// Akcja
_calculator.ProcessDigit(Digit.One);
_calculator.ProcessDigit(Digit.Four);
_calculator.ProcessOperator(Operator.Mul
tiply);
_calculator.ProcessDigit(Digit.Three);
// Asercja
Assert.AreEqual(42,
_calculator.DisplayedValue);
}
}
Jak na razie wygląda to dosyć prosto. Ale powyższy przykład jest bardzo
trzeba było utworzyć dla niej interfejs użytkownika, wówczas warstwa tego
większość klas nie jest klasami samodzielnymi. Zależą one od wielu innych
maszynie.
wiarygodny.
działać poprawnie.
Atrapy
końcu testu i zweryfikowanie jego zawartości. Ale nie będzie to zbyt dobry
dlaczego musimy tak bardzo komplikować rzeczy tylko po to, aby móc
zapisać jakiś wiersz do pliku, ale wkrótce przekonamy się dlaczego tak jest.
CalculatorEngine i LogWriter.
klasę. Jak wskazuje nazwa tej klasy, jest ona czymś, co nazywamy zwykle
atrapą (mock).
[TestClass]
public class CalculatorEngineTests
{
private CalculatorEngine _calculator;
private MockLogWriter _mockWriter;
[TestInitialize]
public void TestInitialize()
{
// Aranżacja
_mockWriter = new MockLogWriter();
_calculator = new
CalculatorEngine(_mockWriter);
}
// ...
[TestMethod]
public void
CalculatorWritesTheExpressionToTheLog()
{
// Akcja
_calculator.ProcessDigit(Digit.Two);
_calculator.ProcessOperator(Operator.Plu
s);
_calculator.ProcessDigit(Digit.Three);
_calculator.ProcessEquals();
// Asercja
Assert.AreEqual("2+3=5",
_mockWriter.LineWritten);
}
}
bardziej złożone niż w tym przykładzie (przy czym jeśli są one zbyt
bibliotek, które pozwalają nam w łatwy sposób tworzyć takie atrapy, bez
klasy MockLogWriter.
[TestClass]
public class CalculatorEngineTests
{
private CalculatorEngine _calculator;
private Mock<ILogWriter> _mockWriter;
[TestInitialize]
public void TestInitialize()
{
// Aranżacja
_mockWriter = new Mock<ILogWriter>();
_calculator = new
CalculatorEngine(_mockWriter.Object);
}
[TestMethod]
public void
CalculatorWritesTheExpressionToTheLog()
{
// Akcja
_calculator.ProcessDigit(Digit.Two);
_calculator.ProcessOperator(Operator.Plu
s);
_calculator.ProcessDigit(Digit.Three);
_calculator.ProcessEquals();
// Asercja
_mockWriter.Verify(
writer => writer.WriteToLog("2+3=5"),
Times.Once);
}
tych zależności testowanego kodu, nawet jeśli nie wykonują one operacji
Czerwone-zielone-refaktoryzacja
Widzieliśmy już w rozdziale 11, jak wygląda pisanie kodu dla czegoś,
dla historyjki użytkownika w cyklu, który trwa zwykle kilka dni, o tyle
kodu, które wyglądają całkowicie inaczej, ale mają taki sam cel. Na
który może wyglądać tak samo, ale używany jest w różnych celach (i
istotny aspekt tego kroku, którego wielu ludzi zwyczajnie nie dostrzega:
duplikacja powinna być usuwana nie tylko z testowanego kodu, ale również
utrzymania kodu.
wywoływana kilka razy na tej samej instancji klasy, zawsze używana jest ta
istniał i nie był pusty). Ponieważ żaden kod nie wywołuje jeszcze tego
tylko tymczasowa.
powinny kończyć się sukcesem, ponieważ stary konstruktor nie jest już
sukcesem.
Ponieważ nikt nie używa już starego przeciążenia tej metody, wszystkie
kod testu, jeśli kod tego testu wywołuje klasę, którą refaktoryzujemy.
produkcyjnego.
testu jest dla większości ludzi nieintuicyjne, tak więc dlaczego powinniśmy
to robić?
Często jest tak, że gdy ludzie piszą najpierw kod, powstałe w ten sposób
Na tym etapie, poza wiedzą w zakresie całej mechaniki, jaka wymagana jest
wcześniej, pozwala nam to jedynie na „czytanie nut”, ale nie pozwala „grać
tyle istotne, aby warto było dla nich pisać testy, budowana jest z dużej
Prawie każda klasa i metoda, która nie została napisana z myślą o testach
metodyki TDD.
pomysł, do którego gorąco zachęcam, ale nie jest to również takie proste,
zachowania, przez co znacznie się one rozrosły. Taka duża klasa lub metoda
Object). Aby ten problem rozwiązać, musimy podzielić taką dużą metodę
Operacje we/wy
Singletony
użytku55 z 1994 roku, znanej również jako książka „Bandy Czterech” (Gang
jednostkowych.
często kod zawierający singletony zawiera ich zbyt wiele, a wiele z nich
Ale jeśli mamy tylko jeden lub dwa singletony, które chcemy
nasza sytuacja jest jeszcze gorsza. Jednak klasę, która używa tych pól,
to wiadome i robimy tak przez cały czas. Ale jeśli tworzymy instancję
oraz obiektu fabryki, który ten obiekt tworzy, musimy wyodrębnić jakiś
}
public class BusinessLogicClass
{
private readonly IDataProviderFactory
_dataProviderFactory;
public
BusinessLogicClass(IDataProviderFactory
dataProviderFactory)
{
_dataProviderFactory =
dataProviderFactory;
}
public void DoSomethingImportant()
{
// ...
var dataProvider =
_dataProviderFactory.CreateInstance();
var data = dataProvider.RetrieveData();
dataProvider.CloseConnection();
// ... użyj danych
}
}
pomocą TDD, czy też nie) wymagają, aby prawie żadna klasa nie miała
właśnie to: pozwala nam ona pisać dobry, modułowy i obiektowy kod,
który jest zwykle łatwy w utrzymaniu. Z tego powodu często mówi się, że
musimy po prostu żyć, nie wystarczy pozwolić, aby testy prowadziły nas
sposób pisania luźno powiązanego kodu, jednak opanowanie tych zasad nie
jest proste.
ZASADY SOLID
współpracujących klas.
oryginalnego zachowania.
bazowe. Innymi słowy: ani klasa bazowa, ani jej klienci nie
w implementujących go klasach.
poziomie pojedynczej klasy nie zawsze jest efektywne i czasem lepiej jest
ekstremalnego, takich jak Kent Beck i Martin Fowler, nie mówi o tym, że
test jednostkowy (lub dowolny test wykonywany w stylu TDD) musi być
testem pojedynczej klasy lub metody, ale jednak w jakiś sposób stało się to
niuansów:
1. W podejściu TDD osoba, która pisze testy jest zwykle tym samym
Ten drugi niuans jest również związany z innym stylem stosowanym przez
w rozdziale 6.
testowany kod będzie dosyć prosty (zwłaszcza gdy nie ma w nim zbyt
Podsumowanie
opanujemy te techniki oraz samą metodykę TDD, nasz kod będzie znacznie
Testy wydajności
Uwaga
naszą organizację.
nie tylko dowiedzieć się, które z operacji wykonywane są przez długi czas,
ale również poznać dokładne scenariusze, w których taka sytuacja ma
Ale nie wszystkie aplikacje nadają się tak samo dobrze na wydania
pomocą testów może być nadal istotne, są aplikacje, które powinny być
wydajności.
Ponadto, gdy pomiar nie jest tak transparentny dla testu, jak w przypadku
w utrzymaniu.
oczekiwanego wyniku.
ostrzegą ich, gdy wydajność każdej operacji była gorsza niż w poprzedniej
2. Same testy można zmienić tak, aby robiły pewne rzeczy w inny sposób,
twardego itd.), profilem sieci, rozmiarem bazy danych itd. Choć najlepsze
sprzętowych.
sam test po kilka razy albo też utworzyć pętlę wewnątrz naszego testu,
w rozdziale 13, ale nie musimy się tutaj zbytnio przejmować matematyką).
obliczyć średnią lub medianę, ale wartości te są zwykle mniej istotne. Przy
mamy potok ciągłego dostarczania, to możemy uczynić ten test częścią jego
bramek.
Ponowne wykorzystywanie kodu pomiędzy testami
funkcjonalnymi i testami wydajności
Choć odradzane jest używanie tych samych testów dla testów wydajności
mieć sens.
czasu zajęło każde wywołanie metody, ile trwała transakcja bazy danych (i
rezultatów może być bardzo proste, ale czasem jest ono bardzo złożone.
jest źródłem wszelkiego zła. Nie zakładajmy, że wiemy, gdzie znajduje się
się mu wydawać, że musi czekać dłużej, niż gdyby operacja taka trwała
łącznie siedem sekund, ale najbardziej istotne dane prezentowane były już
dodatkowych pięciu.
Testy obciążeniowe
powodu wiele osób myli je ze sobą), to mierzą one zupełnie inną rzecz.
nie jest ona zbyt wysoka, lub tylko jakiś procent tej liczby, który potem
staje się mniej istotny w erze chmury, ponieważ zasoby mogą być
dynamicznie pobierane lub zwalniane zgodnie z wykonywanymi na żywo
Każde z nich ma inne funkcje i zalety, ale ich podstawowa idea jest zawsze
możemy zostać zmuszeni użyć więcej niż jednej takiej maszyny (agenta) do
zasymulowania pożądanego obciążenia. Obecnie często agenci testowania
Kolejną rzeczą, jaką warto podkreślić, jest to, że nie ma sensu testować
możliwości:
I tak dalej.
Definiowanie progów
sieci, procesora itd.). Z tego powodu zwykle nie ograniczamy się jedynie do
i diagnostyki.
przed awarią.
Aby dowiedzieć się, jakie powinny być te progi, musimy najpierw zmierzyć
obciążeniowe tylko raz, aby dokonać pomiaru tych wartości. Ale nawet
witryna musi pozyskać fonty z usługi Google Fonts), ale ponieważ w teście
uruchamiać testy dla małej liczby użytkowników i przez krótki okres czasu,
ewoluowania aplikacja.
obciążeniu systemu.
testów. Jeśli przetwarzanie po stronie klienta jest pomijalne lub stałe i nie
serwera.
Testowanie wdrożenia
nasz system.
najpierw wziąć pod uwagę te aspekty izolacji, które mogą nie wpasować się
dostawców.
kilka z nich i upewnić się, że są one bezpieczne dla tego środowiska. Jeśli
nie jesteśmy tego pewni, chcemy być po bezpiecznej stronie lub też wiemy,
raczej chcieli dać testowi jedną lub dwie dodatkowe szanse w przypadku
utworzyć zadanie wsadowe, które usuwa te dane raz na jeden lub kilka dni.
nie będzie mieć ono wpływu na żaden test, który jest obecnie wykonywany.
Testowanie wizualne
to nie weryfikują one, czy interfejs ten wyświetla się prawidłowo. Kolory,
tych elementów jest to, że właściwości te mogą się bardzo często zmieniać
Uwaga
Ponieważ ścisłe porównywanie obrazu piksel po pikselu jest
referencyjne.
zaktualizować obraz referencyjny bądź też, jeśli różnica taka jest błędem,
zrzutów ekranu robionych przez test. Choć jak już wiemy z rozdziału 2,
jeśli coś się nie zmienia, to nie ma większego sensu tego testować.
nowo.
wyglądać wszędzie tak samo, to niestety nie zawsze tak jest. Te różne
Testy instalacji
oraz cel takiego programu instalacyjnego same w sobie nie stanowią żadnej
błędy, a także sprawić, że test będzie bardzo kruchy. Fakt, iż test zakończył
test nie był świadomy. W podobny sposób, test może zakończyć się
niepowodzeniem z powodu brakującego pliku, podczas gdy plik ten nie jest
zainstalowana.
Wadą tego podejścia jest to, że sprawdza ono jedynie jeden pozytywny
itd.
interfejsu użytkownika.
powinno być zwykle usunięcie wszystkich plików tej aplikacji, ale niekiedy
Testy aktualizacji
w nowej wersji).
nowszego formatu).
takie nie będzie już czyste, dlatego możemy nie wiedzieć, czy nasze
coraz bardziej popularny, aby nie powiedzieć, że jego użycie jest dzisiaj po
algorytmu.
uzyskać rezultat „3”, ponieważ kot znajduje się tylko na trzech obrazach.
obraz naraz i zwraca listę obiektów, które zostały na nim rozpoznane. Dla
obrazie, więc możemy jej przesyłać zawsze ten sam obraz złożony
razem zwracała ona inny wynik. W teście możemy określić wyniki, jakie
[cat] przy drugim wywołaniu, [bottle, cat] przy trzecim oraz [car] przy
algorytmem, ale nie chcemy, aby jego błędne wyniki miały wpływ na
Korzystanie z progów
zwracając jeden konkretny rezultat. Ale inne algorytmy zwracają jedną lub
na to, czy chcemy kompleksowo przetestować sam algorytm, czy też całą
w formie zakresu. W niektórych sytuacjach zakres ten może być taki sam
dla wszystkich przypadków, ale niekiedy powinien on być inny dla każdego
99%) i dla naszych testów możemy użyć węższego zakresu (np. 98–100%).
w algorytmie.
więc bezpiecznie użyć zakresu od 110 do 150 osób. Dokładny zakres trzeba
dostarcza się zestaw danych uczących, które składają się zarówno z danych,
danych i wywołuje na nich algorytm. Test ten może stanowić test regresji
sukcesem. Należy ustawić jakiś próg dla liczby lub procentu niepowodzeń,
nasz bieżący algorytm dosyć dobrze wykonuje swoją pracę i że nasze progi
aplikacji.
atrapy dla generatora liczb losowych, ponieważ daje nam ono pełną
generowania ciągu liczb, które mają mniej lub bardziej jednakowy rozkład.
Aby ciąg ten był za każdym razem inny, zwykle jako wartość początkową
dla tego ciągu wykorzystują one liczbę milisekund lub cykli systemowych,
to jednak zmiana ta jest zwykle znacznie prostsza. Nie daje nam to jednak
i wypełnić jedynie tymi danymi, które są potrzebne i istotne dla tego testu.
w zakresach 0–1, 1–3, 3–5, 5–10, 10–20 i ponad 20 lat, to dla każdej z tych
rezultaty.
Chociaż większość aplikacji BI jest dosyć złożona, wykonuje wiele
Podsumowanie
zobaczyliśmy jeden lub więcej sposób ich rozwiązania. Ale to tylko ich
automatyzacji testów nie kończy się w tym miejscu, a dopiero się zaczyna.
Tak naprawdę można powiedzieć, że nigdy się ona nie skończy. Oto kilka
Popełniaj błędy
Jeśli jednak będziemy bali się popełniać błędy, to nigdy do niczego nie
wcześniej.
słuchajmy uważnie również tych osób, których opinie nie są dla nas aż tak
poznamy ich odmienny punkt widzenia, który również może być bardzo
cenny.
Ponadto nie bójmy się prosić innych o pomoc, prosić o opinie lub
zadawać pytania. Pamiętajmy: jedynym głupim pytaniem jest to, które nie
konsultanta na pół etatu, czy też jako pracownika na pełny etat. Oczywiście
jako konsultanta można również zatrudnić także mnie, autora tej książki (po
adresem https://www.linkedin.com/in/arnonaxelrod/).
Zanim jednak poprosimy kogoś innego o pomoc, to przynajmniej
problem.
inne cele lub strategie ich realizacji. Zrozumienie potrzeb i celów naszej
przez długi czas, ale znają i wykorzystują jedynie niewielką część jego
się inni, dzięki czemu nasza wiedza na jego temat będzie jeszcze lepsza. Co
wyjątków itd.
W książce tej odnosimy się do kilku innych podręczników
testami.
spędzić kilka lat na stanowisku dewelopera aplikacji. Dzięki temu nie tylko
perspektywy.
zmiany.
Oczywiście spędzenie kilku lat w roli testera QA pomoże nam lepiej poznać
stawiane przed nimi problemy, ich punkt widzenia oraz sposób myślenia.
Jak tylko dowiemy się czegoś nowego na jakiś temat, to powinniśmy się tą
wiedzą podzielić z innymi, nawet jeśli wydaje się nam, że to nic ważnego
wartość ta wiedza będzie mieć dla innych osób. Dzisiaj bardzo łatwo jest
własnego blogu. Próba opisania jakiejś rzeczy w celu jej objaśnienia innym
Poza pisaniem bloga możemy również dzielić się swoją wiedzą jako
(lub w postaci narzędzi, które można pobrać lub używać online). Jeśli kod
ten lub narzędzie faktycznie okaże się przydatne dla innych, to z pewnością
popularnym projektem open source może mieć takie same korzyści dla
w ogóle w tej książce, ale najważniejsze jest to, abyśmy zawsze byli
przeciwsłonecznym.
Dodatek A. Rzeczywiste przykłady
wodomierzy
między nimi:
Klient sieci Web jest stroną HTML z plikami JavaScript i CSS, które
warstwy danych.
Potem zapytałem ich, w jaki sposób wykonali oni dzisiaj swoje testy
manualne. Okazało się, że wykorzystują oni bazę danych, która jest kopią
zespół ten zdał sobie sprawę, że w ogóle nie testuje komponentu agregatora
danych, mimo że znajduje się w nim spora część logiki. Gdy zaczęliśmy
wzajemnie wpływać.
będzie nam mógł w tym pomóc, na co ten niezwłocznie się zgodził! Okazało
protokołu, a jeśli informacje te nie będą dla nas wystarczająco jasne lub
wodomierzy
Google Maps
zdałem sobie sprawę, że nie wykonują oni testów w niedziele. Dla wielu
osób może się to wydawać oczywiste, ale jeśli weźmiemy pod uwagę to, że
testy nie mogą być uruchamiane w niedziele, ponieważ giełdy nie operują
działać w niedziele, ale nadal nie mogłem pojąć, dlaczego tego dnia nie
giełd z całego świata, a gdy handel się nie odbywa, wiele funkcji aplikacji
testowanie w niedziele.
więc testy nie tylko były uzależnione od istnienia określonych akcji, ale
w handlu. Oczywiście sam test nie miał nad tym żadnej kontroli, a było to
usługi handlowej. Przykładowo nie można było wstępnie ustalić straty lub
zachowania akcji.
Rozwiązanie
W ten sposób zyskaliśmy lepszą kontrolę nad tym, co dzieje się w testach
wcześniej nie dało się przetestować. Oczywiście dzięki temu testy stały się
CRM, która z kolei sprawiała, że testy serwera sieci Web nie były
wiarygodne.
Izolowanie środowisk
kompilacja (która uruchamiała się co noc, ale mogła być również wyzwalana
środowiska testowego.
Rysunek A.6. Końcowa architektura środowiska testowego
Opis architektury
serwera siedziby głównej, ale to leży już poza zakresem tego schematu.
użytkownika.
obsłużone w danej kasie podczas tego samego dnia, baza danych sklepu
wybranych sklepów.
„trójwarstwowym”.
Wdrożenie minimalne
maszynie będącej kasą fiskalną. Zwykle będzie tam również jeden serwer
zarządzania, ale nawet on nie jest wymagany, ponieważ zamiast tego dane
wdrożenia.
współzależności.
Struktura organizacyjna
grupę złożoną z około 200 osób: około połowa z nich to deweloperzy, zaś
zespół dla aplikacji zarządzania, kolejny zespół dla klienta kasy fiskalnej
Scrum.
Rozwiązania automatyzacji testów
wszystkich komponentów.
a także tego, że warstwa usług również była udostępniona jako API REST,
Ogólne zalecenie było takie, aby poza kilkoma testami komponentów, które
tak czy inaczej były wykonywane, zespół napisał co najmniej jeden test
serwer i bazę danych jako jedną jednostkę, komunikując się z nią wyłącznie
wszystkich testów.
komponentów.
każdej konfiguracji.
danych, które pozwoliło nam dowiedzieć się, kiedy zakończył się proces
czasu i ani sekundy dłużej. Ponieważ jednak testy te były dużo wolniejsze
(około 1 minuty na test, zamiast 1 sekundy), uruchamianie ich w CI nie
był w nocy.
Testy kompleksowe
mimo że były one pokryte przez testy jednostkowe, nie wystarczyło tylko
test nie jest łatwe i może być podatne na błędy, przy czym można utworzyć
wyjaśnia, w jaki sposób krok po kroku utworzyć taki mechanizm oraz jak
razu, natomiast do innych bibliotek platformy .NET (np. NUnit lub xUnit)
Problem
cofnięte (np. tworzy jednostki, które należy usunąć), a czwarta operacja nie
powiedzie się, to będziemy chcieli, aby tylko trzy pierwsze operacje zostały
Proste rozwiązanie
lub zmieniającej stan środowiska, powinniśmy dodać do tej listy delegat dla
na listingu B.3.
private readonly List<Action> _cleanupActions =
new List<Action>();
private void AddCleanupAction(Action
cleanupAction)
{
_cleanupActions.Add(cleanupAction);
}
[TestCleanup]
public void Cleanup()
{
foreach (var action in _cleanupActions)
{
action();
}
}
[TestMethod]
public void CouponGivesPriceReduction()
{
var usbCable = AddProductToCatalog("USB
Cable", price: 3);
AddCleanupAction(() =>
RemoveProductFromCatalog(usbCable));
var phoneHolder =
AddProductToCatalog("Smartphone car
holder", price: 20);
AddCleanupAction(() =>
RemoveProductFromCatalog(phoneHolder));
var adapter = AddProductToCatalog("Car AC to
USB adapter", price: 7);
AddCleanupAction(() =>
RemoveProductFromCatalog(adapter));
var coupon = DefineCouponDetails("12345",
percentsReduction: 20);
AddCleanupAction(() =>
RemoveCouponDefinition(coupon));
var totalBeforeCoupon =
shoppingCart.GetTotal();
Assert.AreEqual(30, totalBeforeCoupon,
"Total before coupon added should be 30
(3+7+20)");
shoppingCart.AddCoupon(coupon);
// Oczekuj 20-procentowej obniżki ceny
decimal expectedTotalAfterCoupon =
totalBeforeCoupon * (1 - 20 / 100);
var totalAfterCoupon =
shoppingCart.GetTotal();
Assert.AreEqual(expectedTotalAfterCoupon,
totalAfterCoupon,
"Total after coupon");
}
testowej
będzie akcja usuwania „USB Cable” (kabel USB) w drugiej instrukcji, tak
RemoveProductFromCatalog i RemoveCouponDefinition.
Metoda AddCleanupAction jedynie dodaje referencję do tych metod do
AddProductToCatalog:
AddCleanupAction(() =>
RemoveProductFromCatalog(product));
return product;
}
AddProductToCatalog
w jakim znajdowała się ona na listingu B.2, ale nadal musimy zadbać o to,
testu.
[TestClass]
public abstract class TestBase {
private List<Action> _cleanupActions = new
List<Action>();
public void AddCleanupAction(Action
cleanupAction)
{
_cleanupActions.Add(cleanupAction);
}
[TestCleanup]
public void Cleanup()
{
foreach (var action in _cleanupActions)
{
action();
}
}
}
bazowej
klasie TestBase.
w celu usunięcia tego kuponu, kod ten zgłosi błąd w metodzie Cleanup,
mówiący, że produkt „USB Cable” nie może zostać usunięty, gdyż nadal są
kupon.
Listing B.7. Metoda testowa, która powinna zakończyć się
pierwszą (niezależną) jednostkę, dla której nie mamy już żadnej zależności.
rozwiązania.
[TestCleanup]
public void Cleanup()
{
_cleanupActions.Reverse();
foreach (var action in _cleanupActions)
{
action();
}
}
Uwaga
nawet nieco bardziej wydajne, ale nie na tyle, aby się tym
przejmować.
się niepowodzeniem, czy też nie, a jeśli tak, to nie ma znaczenia, w którym
się niepowodzeniem. Jednak zazwyczaj tak nie jest, tak więc możemy
akcje oczyszczające.
AggregateException, jeśli jest ich więcej niż jeden. Jeśli był tylko
wyjątków.
[TestCleanup]
public void Cleanup()
{
_cleanupActions.Reverse();
var exceptions = new List<Exception>();
if (exceptions.Count > 1)
throw new AggregateException(
"Multiple exceptions occurred in
Cleanup.", exceptions);
}
Uwaga
W przypadku platformy .NET zaleca się wykorzystywanie listy
C.
Podsumowanie
niepowodzeń.
Dodatek C. Projekt „Test
Automation Essentials”
Ten dodatek opisuje utworzony przeze mnie projekt open source o nazwie
Kontekst
klienta, było również przydatnych dla pozostałych klientów. Jak można się
ten kod moim klientom. Ponieważ naturalnie moi klienci nie współdzielą
który będzie służył nam wszystkim. Z czasem, gdy tylko napisałem coś, co
mogło być przydatne dla moich klientów lub jakieś innej osoby, dodawałem
to do projektu. Kod źródłowy tego projektu dostępny jest pod adresem
http://github.com/arnonax/TestEssentials.
pokryć komentarzami XML resztę klas i metod, dla których jeszcze tego
nie zrobiłem.
Struktura projektu
każdy będzie mógł używać jedynie tych bibliotek, które pasują do jego
projekty wewnętrzne:
TestAutomationEssentials.Common
i TestAutomationEssentials.MSTest.
TestAutomationEssentials.MSTectV2UnitTests – zawiera testy
TestAutomationEssentials.MSTestV2.
Wskazówka
jednostkowe dla większości tego kodu, aby upewnić się, że nie popsuję
kompatybilności, gdy będę coś modyfikował. Niestety zajmuje to trochę
Pakiety NuGet
Aby móc korzystać z tych narzędzi, nie musimy pobierać kodu źródłowego
Funkcje i narzędzia
z tych bibliotek.
TestAutomationEssentials.Common
warunku.
Klasa ExtensionMethods
mogą nieco uprościć nasz kod i ułatwić jego czytanie. Na listingu C.1
{1, "One" },
{2, "Two" },
{3, "Three" }
};
var moreNumbers = new Dictionary<int, string>()
{
{4, "Four"},
{5, "Five"},
{6, "Six"}
};
numbers.AddRange(moreNumbers);
niektóre osoby mogą uznać taką składnię za niejasną, ale gdy już do niej
TestExecutionScopeManager
Ta klasa implementuje mechanizm czyszczenia, który opisywany jest
Wait
wykonana bardzo szybko, więc komunikat ten pojawi się jedynie przez
ułamek sekundy. Nasz test może więc nawet wcale nie zauważyć tego
TestAutomationEssentials.MSTest
dla wszystkich naszych testów. Jeśli mamy już hierarchię klas testów, po
z tej klasy.
LoggerAssert
bez względu na to, czy kończy się ona sukcesem, czy porażką. Choć
więcej niż kilka asercji, to istnieją przypadki, w których może się przydać
kilka asercji znajdujących się w środku testu (np. wewnątrz pętli, które
a nie tylko te, które kończą się niepowodzeniem. Zwróćmy uwagę na to, że
TestAutomationEssentials.CodedUI
var customerDetailsPanel =
mainWindow.Find<WinPane>
(By.AutomationId("CustomerDetails"));
var customerNameTextBox =
customerDetailsPanel.Find<WinText>
(By.Name("CustomerName"));
var text = customerNameTextBox.DisplayText;
jak: myControl.RightClick(),
myControl.DragTo(otherControl) oraz bardzo przydatną metodę
myControl.IsVisible(), której z jakiegoś powodu nie dostarcza
biblioteka CodedUI.
TestAutomationEssentials.Selenium
Uwaga
WaitForElement
Aby korzystać z większość funkcji tej biblioteki, musimy utworzyć
aplikacji sieci Web, które wykorzystują wiele okien lub elementów iframe
driver.SwitchTo().Window() oraz
driver.SwitchTo().Frame(), aby korzystać z innych okien
i podatny na błędy.
tak więc nie musimy się nim przejmować. Gdy tylko chcemy użyć
Essentials
Dobrą stroną projektów open source jest to, że każdy może przyczynić się
potrzebowałem, tak więc może w nim nadal brakować wielu rzeczy, które
powinny się w nim znaleźć. Ponadto, mimo że projekt ten jest bardzo
się w nim znaleźć, a co nie. Można zatem zawrzeć w nim każdy dobry
zrobię to, gdy będę miał jakiś rzeczywisty i istotny projekt automatyzacji
testów, który będzie tego wymagał, ale każdy może to zrobić. Zwróćmy
przeznaczone dla języka C#, natomiast inne narzędzia mogą być przydatne
Jeśli chcemy, aby nasza praca z kodem była bardziej wydajna, powinniśmy
korzystania z klawiatury wymaga czasu, ale gdy już tak się stanie,
odpowiedniki tych skrótów, ale mogą być one również całkiem inne.
położyć mysz nieco dalej niż do tej pory i sięgać po nią jedynie wtedy,
O.
pól tekstowych, ale inne kontrolki, takie jak przyciski, pola wyboru,
tekstu) o jedno słowo w przód lub w tył. Klawisze Home oraz End
11. Wciśnięcie klawiszy Shift + Del lub Shift + Backspace usuwa następne
lub poprzednie słowo (lub tekst od środka słowa do jego końca lub
początku).
12. Warto przeszukać sieć pod kątem listy skrótów dla naszego ulubionego
Poka-Yoke
może być uznawane za gorszą opcję. Nam jednak chodziło o to, aby nikt
nie mógł nigdy zmienić tej właściwości z zewnątrz jej klasy (zwróćmy
sobie teraz, czym jest „poka-yoke” i dlaczego termin ten jest tak istotny.
metody tej samej klasy będą miały do niego dostęp, czy też publiczny
niż to, w którym zgłaszany jest wyjątek. Co więcej, przyczyną tych błędów
z „zewnątrz”, która może być wartością null (z miejsca, nad którym nie
potencjalnych błędów!
temu ich kod jest bardziej solidny i niezawodny. Cóż, prawda jest taka, że
obiektu wywołującego (i jeśli nasz kod jest metodą „main” lub metodą
wrażenie, że kod jest bardziej solidny. Powodem tego jest fakt, że jeśli coś
wyjątki, to program nigdy nie ulegnie awarii, ale może również nie robić
pliku”, gdy aplikacja próbuje odczytać z pliku, który mógł zostać usunięty
i odpowiednie jej obsłużenie (np. sprawdzenie, czy plik istnieje, a jeśli nie,
ogólnych, których nie da się przewidzieć ani też podać przyczyny ich
wystąpień, lub gdy nie możemy z nimi nic zrobić (np. „brak pamięci”),
przypadków:
systemie.
usługi REST itd. W takiej metodzie wiele rzeczy może pójść nie tak, ale
natywne wyjątki, które mogą zostać zgłoszone, mogą mieć zbyt niski
poziom, aby były dla nas przydatne i nie powiedzą nam, w jaki sposób
operacji bez ingerencji człowieka nic nam nie da! Jeśli przechwycimy zbyt
problemy:
przydatne dla każdego, kto będzie musiał potem zrozumieć, co się stało.
nigdy nie należy zwracać kodu błędu lub wartości logicznej w celu
danych.
następujące lokalizatory:
formularza HTML.
3. LinkText – identyfikuje elementy poprzez dopasowanie ich
klas. Atrybut class elementu HTML może zawierać zero lub więcej
elementów.
nam pierwszy z nich, który niekoniecznie musi być tym, jaki nas interesuje.
Tak czy inaczej, choć używany przez nas lokalizator musi jednoznacznie
zmodyfikowany.
name tylko wtedy, gdy jego wartość jest wymowną nazwą, powiązaną
słowy, używamy ich tylko wtedy, gdy jego wartość została wybrana przez
elementem, to powinniśmy jej użyć. Jeśli jednak nazwa klasy nie ma nic
nie jest w stanie przewidzieć tego, co może się zmienić w przyszłości lub
wykorzystania.
jest użycie wzorca obiektu strony (Page Object Pattern) dla każdego takiego
również jako stałe tekstowe lub trwale zakodowane ciągi znaków). Nawet
od algorytmu.
występuje.
5. Długość – czasem ciągi znaków mogą stać się bardzo długie, a jeśli
je stosować:
izolacji (patrz rozdział 7), niektóre z tych informacji mogą być różne
przy czym niektóre wartości mogą być stałe dla wszystkich środowisk
przyszłości. Nie oznacza to, że w ogóle nie mogą się one zmieniać
w przyszłości, ale na razie nie ma żadnego powodu, by przypuszczać,
definicji tej stałej i jej zmiana nie powinno nam sprawić problemu. Jeśli
komplikujmy rzeczy!
2. Wartości lokalizatora (Id, XPath, CSS Selector itd.) – bez względu na to,
czy testy API REST (lub może testy jakiegoś innego rodzaju), musimy
utrzymania kodu. Cóż, być może faktycznie dzięki temu „kod” będzie
zrozumienia i śledzenia.
powinniśmy używać tylko dla wartości, które muszą być różne w różnych
środowiskach.
Przypisy