Suggerimenti per i test potenziati per il 2019: un tutorial per i test di automazione Java

Pubblicato: 2022-03-11

Ogni anno, gli ingegneri dell'automazione dei test di tutto il mondo ricercheranno gli strumenti e le tecniche più recenti per rendere il loro framework di automazione dei test più stabile, più veloce e più facile da usare e mantenere. Ciò è fondamentale per garantire l'adozione continua e diffusa del loro quadro all'interno della loro azienda. In generale, i framework gonfi e obsoleti passano rapidamente di moda.

In questo articolo, daremo un'occhiata ad alcuni dei modi in cui puoi aggiornare il tuo framework per il 2019 e come essere preparato per il 2020. Per migliorare il mio framework, mi concentro sempre sui "punti deboli". Queste sono le aree complesse da configurare o che causano il maggior numero di errori. Ho identificato tre aree principali che volevo semplificare o migliorare:

  1. Griglia al selenio
  2. Aspetta
  3. Strumenti di sviluppo di Chrome

Selenium Grid è notoriamente difficile da configurare e può fallire senza preavviso. Volevo vedere cosa, se non altro, era migliorato qui. Volevo anche indagare se sono state aggiunte nuove waits all'API Selenium per migliorare la stabilità di eventuali test che ho creato. Infine, volevo vedere se potevo iniziare a interagire con Chrome DevTools tramite Selenium, che è diventato una parte essenziale del toolkit di qualsiasi tester.

Suggerimento n. 1: Dockerizza la tua griglia di selenio

Selenium Grid è notoriamente difficile da configurare, instabile e difficile da implementare o controllare la versione su una pipeline CI. Un modo molto più semplice, stabile e manutenibile consiste nell'utilizzare le immagini Selenium Docker predefinite.

Nota: l'unico aspetto negativo di questo metodo è che IE (Internet Explorer) non è supportato, poiché non è ancora possibile containerizzare il sistema operativo Windows.

Prepararsi

Per iniziare a funzionare, devi prima avere Docker e Docker Compose installati sul tuo computer. Se utilizzi Windows 10 o un Mac, verranno entrambi installati tramite Docker Desktop.

Iniziare la tua griglia

Il repository Selenium ufficiale su Docker Hub contiene immagini Docker predefinite per Selenium Hub e Firefox e Chrome Nodes.

Il modo più semplice per utilizzarli in una griglia Selenium locale è costruire un file Docker Compose all'interno della directory principale del progetto. Assegna un nome al file docker-compose.yml per semplificare le cose.

Ho incluso un esempio di seguito che crea la seguente griglia:

  • Un unico hub di selenio
  • Un nodo Chrome
  • Un nodo 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

Il file Docker Compose descrive la configurazione della tua griglia. Per ulteriori informazioni sulla creazione di file Docker Compose, consultare la documentazione ufficiale.

Per avviare la tua griglia, usa semplicemente qualsiasi finestra del terminale (una finestra di powershell o cmd in Windows) per eseguire il seguente comando dalla directory principale del tuo progetto:

 docker-compose up

Collegamento alla rete

Puoi connetterti al tuo Selenium Grid esattamente nello stesso modo in cui fai normalmente, poiché l'Hub è in ascolto sulla porta 4444 del tuo computer locale. Ecco un esempio in cui abbiamo impostato il nostro driver per utilizzare il nostro nodo 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);

È quindi possibile utilizzare la libreria TestNG per eseguire i test su più nodi in parallelo come al solito.

Vale la pena notare che è possibile avere più browser in esecuzione su ciascun nodo. Tuttavia, questo è sconsigliato e l'utilizzo di un browser per nodo è considerata la migliore pratica per prestazioni ottimali.

Suggerimenti e trucchi aggiuntivi

Se vuoi vedere cosa sta succedendo sul browser in modo da poter eseguire il debug dei tuoi test, allora vale la pena avere una versione di debug del tuo file docker-compose.yml che scarichi i nodi del browser di debug . Questi contengono un server VNC in modo da poter guardare il browser durante l'esecuzione del test.

È anche possibile eseguire i browser senza testa per una maggiore velocità (il solito modo) e Selenium fornisce anche versioni di base delle immagini in modo da poter creare le tue immagini se hai bisogno di software aggiuntivo installato.

Per creare una versione stabile della griglia per la tua pipeline CI, è anche possibile distribuire la tua griglia su Kubernetes o Swarm. Ciò garantisce che tutti i Docker vengano ripristinati o sostituiti rapidamente in caso di errore.

Suggerimento n. 2: attese intelligenti

Come ogni ingegnere di test automation sa, le waits sono fondamentali per la stabilità del tuo framework di test automation. Possono anche velocizzare il test rendendo ridondanti eventuali sleeps o pauses e superare i problemi di rete lenta e cross-browser. Di seguito sono riportati alcuni suggerimenti per rendere le tue waits ancora più resilienti.

Tutorial sui test di automazione Java n. 2: operatori logici in attesa: sii specifico con le tue attese

La classe ExpectedConditions è cresciuta nel tempo e ora comprende quasi tutte le situazioni immaginabili. Sebbene ExpectedConditions.presenceOfElementLocated(locator) sia spesso sufficiente, è consigliabile utilizzare i metodi all'interno della classe ExpectedCondition per coprire ogni azione dell'utente incorporandola nella classe Actions.java . Questo renderà i tuoi test a prova di proiettile contro la maggior parte dei problemi cross-browser o dei siti Web lenti.

Ad esempio , se facendo clic su un collegamento si apre una nuova scheda, utilizzare ExpectedConditions.numberOfWindowsToBe(2) . Ciò assicurerà che la scheda sia presente prima di provare a passare ad essa.

Puoi anche utilizzare wait per assicurarti di acquisire tutti gli elementi presenti nella pagina quando usi findElements . Ciò può essere particolarmente utile se una pagina di search impiega del tempo per restituire i risultati. Ad esempio, questa riga:

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

Potrebbe risultare in un array List vuoto se i risultati della ricerca non sono ancora stati caricati. Invece, è meglio usare la condizione numberOfElementsToBeMoreThan prevista per attendere che i risultati siano maggiori di zero. Per esempio:

 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();

Ora, il tuo comando findElements verrà eseguito solo dopo che i risultati della ricerca sono stati restituiti.

Questa wait è utile anche per trovare un singolo elemento quando hai a che fare con un front-end che non funziona bene con Selenium (ad esempio, siti Web Angular). La creazione di un metodo come questo proteggerà i tuoi test, rendendoli molto più stabili.

 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); }

È anche possibile attendere che gli elementi non siano più visibili. Ciò è particolarmente utile se stai aspettando che un popup scompaia dopo aver fatto clic sul pulsante OK o Save prima di procedere con il test.

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

Tutti i metodi sopra descritti e altri sono elencati nella documentazione ufficiale. Vale la pena spendere dieci minuti per leggere tutte le possibilità e migliorare la stabilità del tuo framework.

Tutorial sui test di automazione Java n. 2: operatori logici in attesa

Un buon modo per creare resilienza nelle tue waits è usare gli operatori logici. Ad esempio, se si desidera verificare che un elemento sia stato individuato E che sia selezionabile, utilizzare il codice seguente (si noti che questi esempi restituiscono un valore booleano):

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

L'operatore OR sarebbe appropriato se non fossi sicuro se il titolo della pagina potrebbe cambiare o meno. Quindi puoi includere un controllo dell'URL se la prima condizione fallisce, per confermare che sei decisamente sulla pagina giusta.

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

Oppure, se si desidera assicurarsi che una casella di controllo non sia più abilitata dopo l'esecuzione di un'azione sulla pagina, l'operatore NOT è appropriato.

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

L'uso degli operatori può rendere le tue waits più resilienti e risultare in test meno fragili.

Suggerimento n. 3: Chrome DevTools: simulazione delle condizioni di rete

L'esecuzione della tua app Web su localhost o su una rete locale può dare una falsa impressione sulle sue prestazioni durante l'esecuzione in natura. La possibilità di limitare varie velocità di upload e download ti darà una migliore rappresentazione di come la tua applicazione verrà eseguita su Internet, dove i timeout possono causare il fallimento delle azioni. Possiamo iniziare a simularlo usando la potenza di DevTools di Chrome.

Il codice seguente aprirà la home page di Toptal utilizzando diverse velocità di download e upload. Innanzitutto, memorizzeremo le nostre velocità in un fornitore di dati TestNG utilizzando il seguente codice:

 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 }, }; } }

Nota: la limitazione di upload e download è in kb/s e la latenza è in ms .

Quindi, possiamo utilizzare questi dati per eseguire il nostro test in diverse condizioni di rete. All'interno del test, CommandExecutor eseguirà il comando nella sessione corrente del browser. Questo a sua volta attiverà le impostazioni necessarie nella funzionalità Strumenti per sviluppatori di Chrome per simulare la nostra rete lenta. Il codice all'interno dell'istruzione if può essere incluso in un metodo @BeforeClass durante l'esecuzione di una suite di test.

 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! } }
Correlati: Build with Confidence: A Guide to JUnit Tests

Suggerimento bonus: come gestire i cookie

I cookie del browser possono causare comportamenti diversi nell'applicazione, a seconda che siano stati salvati o meno da una sessione precedente (ad esempio, l'applicazione potrebbe essere caricata con un utente già connesso). È buona norma cancellare i cookie prima di ogni esecuzione di test per assicurarsi che non causino problemi.

Il codice seguente consente di eliminare tutti i cookie:

 driver.manage().deleteAllCookies();

Puoi anche eliminare un cookie per nome:

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

Oppure ottieni il contenuto di un cookie:

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

Oppure prendi tutti i cookie:

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

Automazione dei test nel 2020: uno sguardo al futuro

Selenium 4 verrà rilasciato nei prossimi mesi. È ancora in fase di sviluppo, ma poiché è già stata rilasciata una versione alpha, vale la pena dare un'occhiata a quali miglioramenti offrirà.

Nota: puoi tenere traccia dei loro progressi guardando la tabella di marcia.

Standardizzazione dei driver Web W3C

Selenium non avrà più bisogno di comunicare con il browser tramite il protocollo JSON wire; invece, i test automatizzati comunicheranno direttamente con il browser. Questo dovrebbe affrontare la famosa natura traballante dei test Selenium, inclusa la protezione dagli aggiornamenti del browser. Si spera che anche la velocità del test aumenti.

Una griglia di selenio più semplice

Selenium Grid sarà più stabile e più facile da configurare e gestire in Selenium 4. Gli utenti non dovranno più configurare e avviare hub e nodi separatamente poiché la griglia fungerà da nodo e hub combinati. Inoltre, ci sarà un migliore supporto per Docker, i test paralleli saranno inclusi in modo nativo e fornirà un'interfaccia utente più informativa. La traccia delle richieste con Hooks ti aiuterà anche a eseguire il debug della tua griglia.

Documentazione

La documentazione di Selenium riceverà una revisione tanto necessaria, non essendo stata aggiornata dal rilascio di Selenium 2.0.

Modifiche all'API

Il supporto per i browser Opera e PhantomJS verrà rimosso. La corsa senza testa può essere eseguita con Chrome o Firefox e Opera è basato su Chromium e quindi il test di Chromium è considerato sufficiente per questo browser.

WebElement.getSize() e WebElement.getLocation() sono ora sostituiti con un unico metodo WebElement.getRect() . Tuttavia, poiché questi sono spesso usati per creare screenshot di un singolo elemento, vale la pena sapere che ci sarà anche un comando API per catturare uno screenshot di un elemento in Selenium 4.

Per WebDriver Window , i metodi getPosition e getSize saranno sostituiti dal metodo getRect e i metodi setPosition e setSize saranno sostituiti dal metodo setRect . Saranno disponibili i metodi a fullscreen e Riduci a minimize , in modo che queste azioni possano essere eseguite all'interno del test.

Altre modifiche degne di nota:

  • La classe Options per ogni browser ora estenderà la classe Capabilities .
  • È stato aggiunto un metodo driver.switchTo().parentFrame() per semplificare la navigazione tra i frame.
  • saranno inclusi dei nice localizzatori che operano a un livello superiore a quelli attuali. Saranno una sottoclasse di By .
  • Ci sarà un'implementazione dell'API DevTools , che consentirà agli utenti di sfruttare le funzionalità offerte dall'utilizzo del Chrome Debugging Protocol (ed equivalenti su altri browser). Questi includono:
    • Schermate a pagina intera (inclusi elementi fuori schermo).
    • Log in streaming.
    • In attesa di eventi di mutazione sulla pagina.
  • Verranno eliminati anche molti metodi e classi deprecati.

Nota: puoi ottenere una versione Alpha di Selenium 4 dal repository Maven. Si consiglia vivamente di provarlo contro il framework attuale (idealmente su un ramo sandbox), quindi sei pronto per il cambiamento.

Conclusione

In questo articolo, ho trattato alcune aree in cui ho migliorato in meglio il mio framework di automazione dei test. Ora è più stabile e utilizzabile di prima, il che avrà un impatto positivo su tutti coloro che sono coinvolti nel ciclo di vita della distribuzione del software.

Apportare le modifiche che ho delineato sopra è un buon inizio, tuttavia, ti consiglio vivamente di rivedere l'intero framework per i "punti deboli", poiché potrebbero esserci miglioramenti che non ho trattato. Ad esempio, stai utilizzando WebDriver Manager per gestire i tuoi driver o li stai ancora aggiornando manualmente?

Consiglierei anche di impostare una data per farlo almeno una volta all'anno, anche se idealmente sarebbe ogni sei mesi. Nell'articolo, ho incluso le modifiche in arrivo in Selenium 4.0. Per favore, controlla tu stesso le versioni alpha di Selenium. I cambiamenti saranno drammatici e dovrai essere preparato. Spero che tu l'abbia trovato utile. Se scopri nuovi metodi o tecniche mentre fai un po' di pulizie di primavera sul tuo framework, condividili con altri lettori di questo blog aggiungendoli alla sezione commenti qui sotto.

Inoltre, se vuoi dare un'occhiata ai test automatizzati in Selenium e come puoi utilizzare i modelli Page Object per scrivere routine di test gestibili e riutilizzabili, dai un'occhiata a Automation in Selenium: Page Object Model e Page Factory .

Correlati: Il linguaggio Dart: quando Java e C# non sono abbastanza nitidi