Superdoładowane wskazówki testowe na rok 2019: samouczek testowania automatyzacji Java

Opublikowany: 2022-03-11

Każdego roku inżynierowie automatyzacji testów z całego świata będą badać najnowsze narzędzia i techniki, aby ich struktura automatyzacji testów była bardziej stabilna, szybsza i łatwiejsza w użyciu i utrzymaniu. Ma to kluczowe znaczenie dla zapewnienia dalszego powszechnego przyjmowania ich ram w ich firmie. Ogólnie rzecz biorąc, rozdęte, nieaktualne struktury szybko wychodzą z mody.

W tym artykule przyjrzymy się niektórym sposobom aktualizacji swojego frameworka na 2019 rok i jak przygotować się na 2020 rok. Aby ulepszyć moje frameworki, zawsze koncentruję się na „bolesnych punktach”. Są to obszary, które są skomplikowane w konfiguracji lub powodują najwięcej awarii. Zidentyfikowałem trzy główne obszary, które chciałem uprościć lub poprawić:

  1. Siatka selenu
  2. Czeka
  3. Narzędzia programistyczne Chrome

Selenium Grid jest bardzo trudny do skonfigurowania i może zawieść bez ostrzeżenia. Chciałem zobaczyć, co, jeśli cokolwiek, uległo tutaj poprawie. Chciałem również sprawdzić, czy do API Selenium dodano jakieś nowe waits , aby poprawić stabilność dowolnych testów, które stworzyłem. Na koniec chciałem sprawdzić, czy mogę zacząć wchodzić w interakcje z Chrome DevTools za pośrednictwem Selenium, które stały się istotną częścią zestawu narzędzi każdego testera.

Wskazówka 1: Dokeryzuj swoją siatkę selenu

Selenium Grid jest notorycznie trudny do skonfigurowania, niestabilny i trudny do wdrożenia lub kontroli wersji w potoku CI. O wiele łatwiejszym, stabilnym i łatwym w utrzymaniu sposobem jest użycie gotowych obrazów Docker Selenium.

Uwaga: jedyną wadą tej metody jest to, że IE (Internet Explorer) nie jest obsługiwany, ponieważ nie jest jeszcze możliwe konteneryzacja systemu operacyjnego Windows.

Przygotowanie

Aby rozpocząć pracę, najpierw musisz mieć zainstalowane Docker i Docker Compose na swoim komputerze. Jeśli używasz systemu Windows 10 lub komputera Mac, oba zostaną zainstalowane za pośrednictwem pulpitu platformy Docker.

Rozpocznij swoją siatkę

Oficjalne repozytorium Selenium na Docker Hub zawiera gotowe obrazy Docker dla Twojego Selenium Hub oraz węzłów Firefox i Chrome.

Najłatwiejszym sposobem użycia ich w lokalnej sieci Selenium Grid jest skonstruowanie pliku Docker Compose w katalogu głównym projektu. Nazwij plik docker-compose.yml , aby wszystko było proste.

Poniżej zamieściłem przykład, który tworzy następującą siatkę:

  • Pojedynczy koncentrator Selenium
  • Jeden węzeł Chrome
  • Jeden węzeł Firefox
 #docker-compose.yml version: "3" services: selenium-hub: image: selenium/hub:3.141.59-neon container_name: selenium-hub ports: - "4444:4444" chrome: image: selenium/node-chrome:3.141.59-neon volumes: - /dev/shm:/dev/shm depends_on: - selenium-hub environment: - HUB_HOST=selenium-hub - HUB_PORT=4444 firefox: image: selenium/node-firefox:3.141.59-neon volumes: - /dev/shm:/dev/shm depends_on: - selenium-hub environment: - HUB_HOST=selenium-hub - HUB_PORT=4444

Plik Docker Compose opisuje konfigurację siatki. Więcej informacji na temat tworzenia plików Docker Compose można znaleźć w oficjalnej dokumentacji.

Aby uruchomić Grid, po prostu użyj dowolnego okna terminala (okna powershell lub cmd w systemie Windows), aby uruchomić następujące polecenie z katalogu głównego projektu:

 docker-compose up

Podłączanie do sieci

Możesz połączyć się z Selenium Grid w dokładnie taki sam sposób, jak zwykle, ponieważ koncentrator nasłuchuje na porcie 4444 twojej lokalnej maszyny. Oto przykład, w którym skonfigurowaliśmy nasz sterownik do korzystania z naszego węzła Chrome.

 // Driver.java protected static RemoteWebDriver browser; DesiredCapabilities cap = new DesiredCapabilities(); ChromeOptions chromeOptions = new ChromeOptions(); cap.setCapability(ChromeOptions.CAPABILITY, chromeOptions); cap.setBrowserName("chrome"); driver = new RemoteWebDriver(cap);

Następnie możesz użyć biblioteki TestNG do równoległego uruchamiania testów na wielu węzłach, jak zwykle.

Warto zauważyć, że na każdym węźle może działać wiele przeglądarek. Jest to jednak odradzane, a używanie jednej przeglądarki na węzeł jest uważane za najlepszą praktykę w celu uzyskania optymalnej wydajności.

Dodatkowe porady i wskazówki

Jeśli chcesz zobaczyć, co dzieje się w przeglądarce, aby móc debugować testy, warto mieć wersję debug pliku docker-compose.yml , która pobiera węzły przeglądarki debug . Zawierają one serwer VNC, dzięki czemu możesz obserwować przeglądarkę podczas uruchamiania testu.

Możliwe jest również bezgłowe uruchamianie przeglądarek w celu zwiększenia szybkości (w zwykły sposób), a Selenium zapewnia również base wersje obrazów, dzięki czemu możesz tworzyć własne obrazy, jeśli potrzebujesz zainstalowanego dodatkowego oprogramowania.

Aby utworzyć stabilną wersję Grid dla potoku CI, możliwe jest również wdrożenie Grid na Kubernetes lub Swarm. Gwarantuje to, że wszystkie dokery zostaną szybko przywrócone lub zastąpione, jeśli ulegną awarii.

Porada 2: Sprytne czekanie

Jak wie każdy inżynier automatyzacji testów, waits są kluczowe dla stabilności struktury automatyzacji testów. Mogą również przyspieszyć test, renderując zbędne sleeps lub pauses , i rozwiązując problemy z wolnymi sieciami i różnymi przeglądarkami. Poniżej znajduje się kilka wskazówek, które sprawią, że Twoje waits będą jeszcze bardziej odporne.

Samouczek testowania automatyzacji Java nr 2: Operatory logiczne w oczekiwaniach: Bądź konkretny w swoich oczekiwaniach

Klasa ExpectedConditions rozrosła się z biegiem czasu i obecnie obejmuje prawie każdą sytuację, jaką można sobie wyobrazić. Chociaż ExpectedConditions.presenceOfElementLocated(locator) jest często wystarczający, najlepszym rozwiązaniem jest użycie metod w klasie ExpectedCondition , aby objąć każdą akcję użytkownika przez osadzenie ich w klasie Actions.java . To uchroni Twoje testy przed większością problemów z różnymi przeglądarkami lub powolną witryną.

Na przykład , jeśli kliknięcie łącza powoduje otwarcie nowej karty, użyj ExpectedConditions.numberOfWindowsToBe(2) . Zapewni to, że karta będzie tam, zanim spróbujesz się do niej przełączyć.

Możesz również użyć wait , aby upewnić się, że przechwycisz wszystkie elementy obecne na stronie podczas korzystania z findElements . Może to być szczególnie przydatne, jeśli strona search potrzebuje czasu, aby zwrócić wyniki. Na przykład ta linia:

 List<WebElement> results = driver.findElements(locators.RESULTS);

Może to spowodować pustą tablicę List , jeśli wyniki wyszukiwania nie zostały jeszcze załadowane. Zamiast tego lepiej jest użyć warunku numberOfElementsToBeMoreThan oczekiwanego, aby poczekać, aż wyniki będą większe niż zero. Na przykład:

 WebElement searchButton = driver.findElement(locators.SEARCH_BUTTON); searchButton.click(); new WebDriverWait(driver, 30) .until(ExpectedConditions .numberOfElementsToBeMoreThan(locators.RESULTS, 0)); List<WebElement> results = driver.findElements(locators.RESULTS); results.get(0).click();

Teraz polecenie findElements zostanie uruchomione dopiero po zwróceniu wyników wyszukiwania.

To wait jest również przydatne do znalezienia pojedynczego elementu, gdy masz do czynienia z interfejsem, który nie współpracuje dobrze z Selenium (np. strony Angular). Stworzenie takiej metody ochroni twoje testy, czyniąc je znacznie bardziej stabilnymi.

 protected static WebElement waitForElement(By locator){ try { new WebDriverWait(browser, 30) .until(ExpectedConditions .numberOfElementsToBeMoreThan(locator, 0)); } catch (TimeoutException e){ e.printStackTrace(); Assert.fail("Timeout: The element couldn't be found in " + WAIT + " seconds!"); } catch (Exception e){ e.printStackTrace(); Assert.fail("Something went wrong!"); } return browser.findElement(locator); }

Można nawet poczekać, aż elementy przestaną być widoczne. Jest to szczególnie przydatne, jeśli czekasz, aż wyskakujące okienko zniknie po kliknięciu przycisku OK lub Save przed kontynuowaniem testu.

 WebElement okButton = driver.findElement(locators.OK_BUTTON); okButton.click(); new WebDriverWait(driver, 30) .until( ExpectedConditions .invisibilityOfElementLocated(locators.POPUP_TITLE) );

Wszystkie metody opisane powyżej i nie tylko są wymienione w oficjalnej dokumentacji. Warto poświęcić dziesięć minut na zapoznanie się ze wszystkimi możliwościami i poprawę stabilności swojego frameworka.

Samouczek testowania automatyzacji Java nr 2: Operatory logiczne w oczekiwaniu

Dobrym sposobem na budowanie odporności w waits jest użycie operatorów logicznych. Na przykład, jeśli chcesz sprawdzić, czy element został zlokalizowany ORAZ czy można go kliknąć, użyj następującego kodu (zwróć uwagę, że te przykłady zwracają wartość logiczną):

 wait.until(ExpectedConditions.and( ExpectedConditions.presenceOfElementLocated(locator), ExpectedConditions.elementToBeClickable(locator) ) );

Operator OR byłby odpowiedni, gdybyś nie był pewien, czy tytuł strony może się zmienić. Następnie możesz dołączyć sprawdzenie adresu URL, jeśli pierwszy warunek nie powiedzie się, aby potwierdzić, że zdecydowanie jesteś na właściwej stronie.

 wait.until(ExpectedConditions.or( ExpectedConditions.titleIs(expectedTitle), ExpectedConditions.urlToBe(expectedUrl) ) );

Lub jeśli chcesz się upewnić, że pole wyboru nie jest już aktywne po wykonaniu akcji na stronie, odpowiedni jest operator NOT.

 wait.until(ExpectedConditions.not( ExpectedConditions.elementToBeClickable(locator) ) );

Korzystanie z operatorów może sprawić, że waits będą bardziej elastyczne, a testy będą mniej kruche.

Porada 3: Narzędzia programistyczne Chrome: symulowanie warunków sieciowych

Uruchamianie aplikacji internetowej na hoście lokalnym lub w sieci lokalnej może dawać fałszywe wrażenie co do jej wydajności podczas działania na wolności. Możliwość ograniczenia różnych prędkości wysyłania i pobierania zapewni lepszą reprezentację tego, jak Twoja aplikacja będzie działać w Internecie, gdzie przekroczenie limitu czasu może spowodować niepowodzenie akcji. Możemy zacząć to symulować, korzystając z możliwości DevTools w Chrome.

Poniższy kod otworzy stronę główną Toptal przy różnych prędkościach pobierania i wysyłania. Najpierw zapiszemy nasze prędkości w dostawcy danych TestNG za pomocą następującego kodu:

 import org.testng.annotations.DataProvider; public class ExcelDataProvider { @DataProvider(name = "networkConditions") public static Object[][] networkConditions() throws Exception { return new Object[][] { // Upload Speed, Dowload Speed in kb/s and latency in ms. { 5000 , 5000, 5 }, { 10000, 7000, 5 }, { 15000, 9000, 5 }, { 20000, 10000, 5 }, { 0, 0 }, }; } }

Uwaga: ograniczanie przesyłania i pobierania jest podawane w kb/s , a opóźnienie w ms .

Następnie możemy wykorzystać te dane do uruchomienia naszego testu w różnych warunkach sieciowych. W ramach testu CommandExecutor wykona polecenie w bieżącej sesji przeglądarki. To z kolei aktywuje niezbędne ustawienia funkcji Narzędzi programistycznych Chrome, aby symulować naszą wolną sieć. Kod w instrukcji if może zostać uwzględniony w metodzie @BeforeClass podczas uruchamiania zestawu testów.

 import org.testng.annotations.Test; import com.google.common.collect.ImmutableMap; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.openqa.selenium.remote.Command; import org.openqa.selenium.remote.CommandExecutor; import org.openqa.selenium.remote.Response; public class TestClass { // load our data provider @Test(dataProvider = "networkConditions") public void test(int download, int upload, int latency) throws IOException { // only run if the network is throttled if (download > 0 && upload > 0) { CommandExecutor executor = driver.getCommandExecutor(); // create a hashmap of the required network conditions Map map = new HashMap(); // you can even test 'offline' behaviour map.put("offline", false); map.put("latency", latency); map.put("download_throughput", downloadThroughput); map.put("upload_throughput", uploadThroughput); // execute our code Response response = executor.execute( new Command(driver.getSessionId(), "setNetworkConditions", ImmutableMap.of("network_conditions", ImmutableMap.copyOf(map)))); } // Open the website driver.get("https://www.toptal.com/"); // You can then check that elements are loaded etc. // Don't forget to use waits! } }
Powiązane: Buduj z ufnością: przewodnik po testach JUnit

Dodatkowa wskazówka: jak zarządzać plikami cookie

Pliki cookie przeglądarki mogą powodować różne zachowania w Twojej aplikacji, w zależności od tego, czy zostały zapisane z poprzedniej sesji (np. aplikacja może zostać załadowana z już zalogowanym użytkownikiem). Dobrą praktyką jest wyczyszczenie plików cookie przed każdym uruchomieniem testu, aby upewnić się, że nie powodują one problemów.

Poniższy kod umożliwia usunięcie wszystkich plików cookie:

 driver.manage().deleteAllCookies();

Możesz również usunąć plik cookie według nazwy:

 driver.manage().deleteCookieNamed("CookieName");

Lub uzyskaj zawartość pliku cookie:

 String myCookie = driver.manage().getCookieNamed("CookieName").getValue();

Lub zdobądź wszystkie ciasteczka:

 List<Cookie> cookies = driver.manage().getCookies();

Automatyzacja testów w 2020 r.: Patrząc w przyszłość

Selenium 4 ukaże się w ciągu najbliższych kilku miesięcy. Wciąż jest w fazie rozwoju, ale ponieważ wersja alfa została już wydana, warto przyjrzeć się, jakie ulepszenia zaoferuje.

Uwaga: możesz śledzić ich postępy, patrząc na mapę drogową.

Standaryzacja sterowników sieciowych W3C

Selenium nie będzie już musiało komunikować się z przeglądarką za pośrednictwem protokołu JSON Wire; zamiast tego automatyczne testy będą komunikować się bezpośrednio z przeglądarką. Powinno to rozwiązać słynną niestabilną naturę testów Selenium, w tym ochronę przed aktualizacjami przeglądarek. Miejmy nadzieję, że prędkość testu również wzrośnie.

Prostsza siatka selenu

Selenium Grid będzie bardziej stabilny i łatwiejszy do skonfigurowania i zarządzania w Selenium 4. Użytkownicy nie będą już musieli konfigurować i uruchamiać hubów i węzłów oddzielnie, ponieważ sieć będzie działać jako połączony węzeł i hub. Ponadto będzie lepsze wsparcie dla platformy Docker, testy równoległe zostaną włączone natywnie i zapewni bardziej informacyjny interfejs użytkownika. Śledzenie żądań za pomocą hooków pomoże również w debugowaniu siatki.

Dokumentacja

Dokumentacja Selenium zostanie bardzo potrzebna, ponieważ nie była aktualizowana od czasu wydania Selenium 2.0.

Zmiany w API

Wsparcie dla przeglądarek Opera i PhantomJS zostanie usunięte. Bezgłowe bieganie można wykonać w przeglądarce Chrome lub Firefox, a Opera jest oparta na Chromium, dlatego testy Chromium są uważane za wystarczające dla tej przeglądarki.

WebElement.getSize() i WebElement.getLocation() są teraz zastąpione pojedynczą metodą WebElement.getRect() . Ponieważ jednak są one często wykorzystywane do tworzenia zrzutów ekranu pojedynczego elementu, warto wiedzieć, że w Selenium 4 pojawi się również polecenie API do przechwycenia zrzutu ekranu elementu.

W przypadku WebDriver Window metody getPosition i getSize zostaną zastąpione metodą getRect , a metody setPosition i setSize zostaną zastąpione metodą setRect . Dostępne będą metody fullscreen i minimize , więc te czynności można wykonać w ramach testu.

Inne ważne zmiany:

  • Klasa Options dla każdej przeglądarki rozszerzy teraz klasę Capabilities .
  • Dodano driver.switchTo().parentFrame() , aby ułatwić nawigację po ramkach.
  • zostaną włączone nice lokalizatory, które działają na wyższym poziomie niż obecne. Będą podklasą By .
  • Zostanie zaimplementowane API DevTools , pozwalające użytkownikom na korzystanie z funkcji oferowanych przez Chrome Debugging Protocol (i jego odpowiedniki w innych przeglądarkach). Obejmują one:
    • Pełne zrzuty ekranu (w tym elementy poza ekranem).
    • Dzienniki przesyłania strumieniowego.
    • Oczekiwanie na zdarzenia mutacji na stronie.
  • Wiele przestarzałych metod i klas zostanie również usuniętych.

Uwaga: Wersję Alpha Selenium 4 można pobrać z repozytorium Maven. Zdecydowanie zaleca się wypróbowanie tego na obecnym frameworku (najlepiej na gałęzi piaskownicy), więc jesteś gotowy na zmianę.

Wniosek

W tym artykule omówiłem kilka obszarów, w których poprawiłem moje ramy automatyzacji testów na lepsze. Jest teraz bardziej stabilny i użyteczny niż wcześniej, co będzie miało pozytywny wpływ na wszystkich zaangażowanych w cykl życia dostarczania oprogramowania.

Dokonanie zmian, które opisałem powyżej, to dobry początek, jednak zdecydowanie zalecam przejrzenie całej struktury pod kątem „bolesnych punktów”, ponieważ mogą istnieć ulepszenia, których nie omówiłem. Na przykład, czy używasz WebDriver Managera do zarządzania sterownikami, czy nadal aktualizujesz je ręcznie?

Sugerowałbym również ustalenie daty co najmniej raz w roku, chociaż najlepiej byłoby to robić co sześć miesięcy. W artykule zamieściłem zmiany, które nadchodzą w Selenium 4.0. Przejrzyj proszę wersje alpha Selenium dla siebie. Zmiany będą dramatyczne i będziesz musiał być przygotowany. Mam nadzieję, że to przydatne. Jeśli podczas wiosennych porządków na swoim frameworku odkryjesz jakieś nowe metody lub techniki, podziel się nimi z innymi czytelnikami tego bloga, dodając je do sekcji komentarzy poniżej.

Ponadto, jeśli chcesz przyjrzeć się automatycznym testom w Selenium i tym, jak używać modeli Page Object do pisania procedur testowych, które można konserwować i wielokrotnego użytku, sprawdź Automatyzacja w Selenium: Page Object Model i Page Factory .

Powiązane: Język Dart: kiedy Java i C# nie są wystarczająco ostre