E2E Testing In Angular 2 From Zero To Hero (Final Part)
Drodzy przyszli mistrzowie Angular 2 E2E Testing.
To jest to. Pod koniec tej lekcji będziesz w końcu miał wszystkie narzędzia do tworzenia testów funkcjonalnych dla swoich aplikacji Angular 2. Koniec z wymówkami: Masz moc!
Najpierw zapoznamy się z Locatorami następnie zobaczymy jak niesamowite mogą być Page Objects, po czym zobaczymy jak radzić sobie z asynchronicznością i w końcu najłatwiejszą część jaką jest wyzwalanie Actions.
Jeśli nie masz podstaw, skieruj się tam, w przeciwnym razie będziesz trochę zagubiony.
Lokatory
Jedną, jeśli nie najważniejszą rzeczą w testowaniu E2E jest znalezienie elementów, które chcesz przetestować w swoim widoku. Przez większość czasu będziesz zadawał sobie pytanie „dlaczego nie mogę znaleźć tego elementu ****?”, po którym następuje „oooohhhhh”.
Masz wiele sposobów, aby to zrobić. Większość z nich zależy od twojej aplikacji. Aby uzyskać swoje elementy, będziesz używał szeregu Lokalizatorów. W większości przypadków, możesz znaleźć swoje elementy przez:
- Nazwa klasy.
- Id.
- Model.
- Binding.
Dla nadchodzących testów, użyjemy tego szablonu.html:
<div class="parent2"> <div class="parent1"> <div class="nested-class" style="color:blue;"> I am a nested element </div> </div></div>
Skupmy się na nested-class i nested-id.
By Class:
Chwycimy tutaj nasz element używając element(by.css(selector)) a następnie testujemy czy jest on obecny czy nie.
By Id:
it("should find the nested id", () => { let elem = element(by.id("nested-id")); expect(elem.getText()).toBe("I am a nested element");});
Chwycimy tutaj nasz element używając element(by.id(elem-id)) a następnie testujemy czy jest on obecny czy nie.
Następujące lokalizatory są bardzo przydatne w AngularJS ale nie są jeszcze zaimplementowane w Angular 2 więc na razie trzymajmy je z boku.
By Model:
it("should find the model", () => { let elem = element(by.model("modelToFind")); expect(elem.isPresent()).toBeTruthy();});
By Bindings:
it("should find the binding", () => { let elem = element(by.model("bindingToFind")); expect(elem.isPresent()).toBeTruthy();});
Aby debugować swoje testy, możesz po prostu dodać „browser.pause()” w swoim teście, będziesz mógł uruchomić wszystkie poprzednie instrukcje i zatrzymać gdziekolwiek chcesz.
Po osiągnięciu pauzy, będziesz miał ekran podobny do tego:
Jak widać na tym obrazku, aby dostać się do fotela kierowcy musisz wpisać repl.
Teraz powiedzmy, że nie masz żadnego testu i chcesz po prostu pobawić się z Protractor. Możesz po prostu wpisać w swoim terminalu:
protractor --elementExplorer
Jeśli masz jakieś problemy ze ścieżką, możesz wpisać:
./node_modules/protractor/bin/elementexplorer.js
Nie musisz wpisywać repl tym razem, po prostu użyj obiektu przeglądarki i jesteś gotowy do żeglowania!
Obiekty stron
Co jeśli masz testy, które dzielą ten sam scenariusz? Czy zamierzasz kopiować i wklejać swój kod wszędzie? A co jeśli ten scenariusz się zmieni? Teraz musisz przejrzeć każdy plik i dokonać modyfikacji.
Tutaj właśnie obiekty Pages stają się bardzo przydatne. Napisz raz, udostępnij wszędzie!
Obiekt strony jest obiektem, który zawiera elementy i scenariusze dotyczące strony.
Na początek bardzo prosty Obiekt Page:
export class HomePage { nestedClass; constructor() { this.nestedClass = element(by.css(".nested-class")); }}
Następnie użyjemy go w naszym teście:
Importujemy Obiekt Page, tworzymy instancję i używamy jego właściwości.
Asynchroniczne przygody
Teraz moi przyjaciele, możecie uzyskać dostęp do dowolnych elementów na waszej stronie! Mam na myśli prawie :).
Będą pewne specjalne przypadki.
Jeśli miałeś (nie)szczęście pracować z jQuery, musisz być zaznajomiony z document.ready().
Przez asynchroniczną naturę JavaScriptu, będą przypadki, w których będziesz próbował uzyskać dostęp do elementu, zanim jeszcze pojawi się on na stronie.
Aby sobie z tym poradzić, będziesz musiał użyć funkcji Protractora, aby poczekać, aż twój element będzie gotowy, zanim zaczniesz go szukać.
Tutaj jest przykład wyświetlania przycisku po upływie limitu czasu.
Najpierw klasa, która zawiera timeout:
export class Home { isHidden = true; triggerTimeOut = ((){ setTimeout(() => this.isHidden = false, 2250) })}
Potem szablon.html:
Mamy tutaj przycisk, który wywoła nasz timeout, po jego wygaśnięciu zostanie wyświetlony tekst.
Tutaj są testy.
Znajdujemy nasz przycisk, klikamy na niego, próbujemy znaleźć nasz tekst ALE spodziewamy się, że go nie będzie.
A oto jak sobie poradzimy z tym przypadkiem ;).
Używamy „browser.wait” w połączeniu z „browser.isElementPresent” testując nasz Locator. Po 5 sekundach wykonywana jest reszta kodu. Nie zapomnij umieścić tutaj timera, w przeciwnym razie twoje testy będą zablokowane na zawsze!
Jeśli więc jeden z twoich elementów ma być tutaj, ale nie możesz go zdobyć, twój instynkt powinien podpowiedzieć ci, abyś zapamiętał to, co właśnie przeczytałeś tutaj.
Actions
Teraz, gdy masz już swój cenny element, wykonałeś 90% pracy!
Jeśli nie możesz go znaleźć, to albo twoja aplikacja nie działa tak, jak powinna (dlatego właśnie robimy testy), albo musisz stać się lepszy w testowaniu i spędzać mniej czasu na Pokemon GO polując na dratinis w pobliżu rzeki o 1 w nocy (wszyscy tam byliśmy…).
Dalej kontynuujmy z akcjami, których możesz użyć na elemencie. Oto one:
Używamy Protractora, który opiera się na WebDriver. Jeśli potrzebujesz bardziej wymyślnych akcji, możesz rzucić okiem na to, co jest dostępne tutaj.
Testujmy niektóre z nich.
Dla szablonu.html:
<input type="text" />
Pobawimy się trochę z wprowadzaniem tekstu. Szybki quiz, co robi ten test (nie czytaj opisu)?
Rozwiązanie: Dostajemy nasze wejście, wpisujemy w środku „Some text”, testujemy, że dostaliśmy ustawioną wartość, czyścimy ją i w końcu testujemy, że wartość jest pusta.
W ostateczności możemy zadać sobie pytanie, jaki jest najlepszy sposób na wyzwalanie akcji? Ten link tutaj pokazuje jedną z wad używania JavaScript zamiast WebDriver.
Z pewnością pisanie w JavaScript jest o wiele bardziej kompaktowe, ale wiąże się z pewnym ryzykiem!
Możesz zrobić wszystko, co chcesz z elementem. Najlepszym sposobem na przetestowanie tego jest użycie matcherów, które są dostępne. Dlaczego? Ponieważ są eleganckie i zbliżone do ludzkiego języka, przykład:
expect(apples.length !== 0).toBe(true);
expect(apples).not.toBeEmpty();
Podsumowanie
To był ostatni post z tej serii, w tej chwili masz 90% umiejętności do testowania swoich aplikacji Angular 2. Pozostałe 10% zdobędziesz poprzez doświadczenie. Pamiętaj, najpierw zdobądź swoje elementy używając Locatorów, następnie umieść ten, który może być replikowany w Page Object, jeśli nie możesz znaleźć swojego elementu, a jesteś pewien, że jest tutaj, może to być spowodowane tym, że jeszcze się nie pojawił i musisz poradzić sobie z asynchronicznością. Na koniec przetestuj **** swoje elementy za pomocą Actions.