Unit Test automatizzati di un’applicazione Web in Python

#Python #Unittest #Selenium #Automation

In questo post, vedremo come unit testare un’applicazione Web in Python per verificare la correttezza delle funzionalità. Whoa! Quella frase ha una manciata di gergo: test unitario, applicazione Web e test di funzionalità.

Abbiamo esaminato unit testing un programma Python in un post precedente. Vi invitiamo a passare attraverso di essa, se non si ha familiarità con unit testing.

Che cos’è un test unitario?

L’unità è una parte testabile più piccola di un programma o di un’applicazione.

Quindi, i test unitari vengono utilizzati per testare a livello di programmazione ogni componente testabile.

È possibile testare un programma back-end o un programma front-end come un’applicazione web.

Per un programma di back-end, si dovrebbe scrivere un test unitario per ogni funzione o metodo nel codice in quanto sono unità logiche più piccole.

Tuttavia, per un frontend, si identificheranno diverse funzionalità che si desidera controllare e scrivere test unitari di conseguenza.

In questo post, ci accingiamo a testare un programma frontend, vale a dire un’applicazione web.

Che cos’è un’applicazione web?

Qualsiasi applicazione che esegue il rendering su un browser Web come Chrome, Firefox o Safari.

Tutte le applicazioni web hanno una cosa in comune: sono visibili agli utenti finali una pagina HTML (Hypertext Markup Language). HTML è semplicemente un linguaggio di formattazione per descrivere come le cose dovrebbero essere organizzate. È semplicemente un file di testo.

I browser ottengono questa pagina HTML e interpretano i tag (ad esempio HEAD, BODY, HREF, TABLE, ecc.) per mostrarti una bella pagina.

Le applicazioni Web funzionano nell’architettura client-server, dove il server Web ospita il contenuto a cui si desidera accedere e il browser Web funge da client.

Architettura Web client-Server

Che cos’è il test di funzionalità?

Come suggerisce il nome, quando scrivi codice di test funzionale, il tuo obiettivo è testare la funzionalità dell’applicazione. In altre parole, si desidera assicurarsi che l’applicazione segua le specifiche funzionali.

Esistono altri tipi di test come test delle prestazioni, test di sicurezza (penetrazione) e test di accettabilità dell’utente.

Il codice di test funzionale che scrivi può essere incluso in quello che viene chiamato un test di regressione che viene eseguito periodicamente per assicurarsi che le vecchie funzionalità non siano interrotte a causa di nuovi sviluppi.

Alla fine di questo post, capirai il codice completo menzionato di seguito.

Non scoraggiarti se ritieni che questo sia troppo. L’obiettivo di questo post è quello di sezionare questo e mostrare come si può capire questo codice e poi scrivere il proprio!

Il diagramma seguente mostra l’approccio di alto livello per testare automaticamente un’applicazione Web (pagina).

Passaggi di test delle applicazioni Web

Per scrivere i nostri test, utilizziamo un framework di test chiamato unittest. È molto simile a junit in Java o nunit in. Net.

unittest consente di raggruppare il codice di inizializzazione in una funzione di installazione e ripulire il codice tin una funzione di tearDown.

Il seguente diagramma mostra l’approccio generale alla base dei test unitari.

Unit test framework

Come si può vedere dal diagramma sopra, una suite di test è costituito da uno o più casi di test.

Un test case può avere uno o più test. In questo post, ci accingiamo a concentrarsi su un caso di test con un test. Mostreremo alla fine come aggiungere più test allo stesso caso di test e creare una suite di test.

Come accennato in precedenza, ogni caso di test ha un setUp (esegui all’inizio) e tearDown (esegui alla fine) metodi per eseguire l’inizializzazione e la pulizia rispettivamente.

Struttura di un test case unitario

Lo snippet di codice sopra riportato mostra la struttura di un test case unitario.

Riga 1: Importa le librerie necessarie. Nel nostro caso, stiamo usando le librerie selenium e unittest.

Riga 3: si crea una classe denominata MyTestCase che estende unittest.Classe TestCase. Diciamo che unittest.TestCase è la classe genitore e MyTestCase è la classe figlio.

Riga 4: Aggiungiamo il nostro codice di inizializzazione nel metodo di installazione. È necessario utilizzare il nome del metodo esatto per far sapere a unittest che si sta aggiungendo il codice di inizializzazione qui. Quando si esegue questo caso di test, questo metodo viene eseguito per primo.

Riga 7: un test di esempio che vogliamo includere nel caso di test.

Linea 10: Un altro test di esempio che abbiamo nel nostro test case.

Riga 16: Aggiungiamo il nostro codice di pulizia all’interno di questo metodo di tearDown. L’opposto del metodo di installazione, il metodo tearDown viene eseguito l’ultimo.

Quindi, l’ordine di invocazione del metodo è:

setUp > test1 > test2 > te > tearDown

Riga 20: Questo dice che il programma principale inizia da questo luogo.

Riga 21: ecco come si esegue il test case.

Ora è il momento per noi di mettere le mani sul test vero e proprio che volevamo fare. Ricordiamo, che vogliamo verificare se la casella di ricerca di Google restituisce almeno 5 risultati per una determinata parola chiave di ricerca.

Diamo un’occhiata al metodo di installazione prima:

In questo frammento di codice, creiamo il driver del browser Chrome.

È necessario scaricare il driver selenium Chrome da qui se non lo si dispone già. Al momento della stesura di questo documento, Chrome ha anche la versione 74. Dal momento che il mio browser Chrome è la versione 73, ho scaricato la versione 73 per questo esercizio.

Le linee 2 e 3 creano l’opzione Chrome e consentono a selenium webdriver di sapere che non vogliamo rendere visibile il browser quando eseguiamo il test.

Se non aggiungi questa opzione, il test si blocca nel punto in cui si apre il browser.

Ora diamo un’occhiata al metodo tearDown:

Abbiamo semplicemente ripulire il driver chiamando il metodo quit ().

Infine, è il momento di dare un’occhiata al test che vogliamo includere in questo caso di test. Ricordiamo che possiamo testare (asserire) se il numero di risultati di ricerca restituiti è maggiore o uguale a 5.

Il codice di prova effettivo

Linea 1: Il metodo di prova inizia con la parola “test”.

Linea 3: Carico www.google.com pagina web nel driver (Si noti che auto.il driver viene creato durante il tempo di installazione).

Linea 6: Individua la casella di ricerca in base al nome dell’elemento HTML “q”. È necessario ispezionare la pagina HTML per identificare questo.

Riga 7: rendi vuota la casella di ricerca nel caso in cui ci siano valori predefiniti.

Riga 10: Riempire la casella di ricerca con la stringa di ricerca “Test automatici”.

Riga 11: Invia la query di ricerca a Google.

Riga 14: XPath che identifica le intestazioni dei risultati di ricerca.

Riga 17: attendere 10 secondi fino al caricamento della pagina dei risultati di Google.

Riga 20: ottieni tutte le intestazioni dei risultati di ricerca utilizzando il percorso X definito nella riga 14.

Linee 25 e 26: Le intestazioni dei risultati della ricerca sono in realtà una lista e le iteriamo attraverso di esse per l’output sullo schermo. Abbiamo aggiunto queste due righe solo a scopo dimostrativo. Di solito, gli script di test non hanno schermi di stampa in quanto non c’è nessuno disponibile a fissare lo schermo per vedere tale output quando automatizzato.

Linea 30: Questo è l’effettivo assert che stiamo facendo. assertGreater è un metodo definito in unittest.Classe TestCase che ci consente di verificare se un output è maggiore del valore some.

unittest.TestCase infatti ci fornisce un insieme di tale metodo per verificare l’uguaglianza, maggiore di, minore di, ecc. a seconda di cosa vuoi affermare. La seguente tabella mostra alcuni dei metodi assert comuni disponibili.

Metodi di asserzione comuni in unittest.TestCase

Come mostrato all’inizio, è possibile scrivere il caso di test invocando quanto segue nel codice:

unittest.main()

Nella riga di comando è sufficiente digitare il nome del file utilizzato per salvare il caso di test.

python google_search_test.py

Esegue setUp (), quindi test_result_count () e infine tearDown ().

Dovresti vedere un output simile al seguente:

Output dell’esecuzione del test case

Se un test fallisce, verrà visualizzato il messaggio FAIL insieme al metodo di test che non è riuscito.

Questo è il tuo primo caso di test Selenium/unittest di successo. Felicitazioni! È una pietra miliare importante.

Bonus

Se hai steam, ti incoraggio a seguire il resto per approfondire ancora di più i test automatizzati delle applicazioni Web di base Selenium/unittest.

Diciamo che vuoi testare se l’intestazione è uguale a “Google”.

Il codice di test appare come segue:

def test_header(self):
self.driver.get("http://www.google.com")
self.assertEqual("Google", self.driver.title)

Ora il nostro intero caso di prova appare come segue:

class GoogleSearchTest(unittest.TestCase):
def setUp(self): def test_header(self): def test_result_count(self): def tearDown(self):
if __name__ == "__main__":
unittest.main()

Supponiamo che le schermate di stampa di cui sopra siano commentate. Quando si esegue il test case aggiornato, si dovrebbe ottenere un output come segue:

test_header (__main__.GoogleSearchTest) ... ok
test_result_count (__main__.GoogleSearchTest) ... ok----------------------------------------------------------------------
Ran 2 tests in 13.799s
OK

Dice che ha eseguito due test ed entrambi hanno successo.

Diciamo che cambio la condizione assertEqual nel primo test al seguente:

self.assertEqual("Microsoft", self.driver.title)

Cosa pensi che succederebbe qui?

Sì, avete indovinato giusto. Il primo caso di test fallirà come self.driver.titolo è uguale a Google, non Microsoft.

Otterrai un output simile al seguente:

test_header (__main__.GoogleSearchTest) ... FAIL
test_result_count (__main__.GoogleSearchTest) ... ok
====================================================================
FAIL: test_header (__main__.GoogleSearchTest)
--------------------------------------------------------------------
Traceback (most recent call last):
File "google_search_test.py", line 19, in test_header
self.assertEqual("Microsoft", self.driver.title)
AssertionError: 'Microsoft' != 'Google'
- Microsoft
+ Google
--------------------------------------------------------------------
Ran 2 tests in 14.011s
FAILED (failures=1)

L’output di cui sopra dice che solo un test ha avuto successo e il fallito.

Quando scrivi i casi di test per la prima volta, potresti incontrare situazioni come questa.

Supponendo che il tuo caso di test sia corretto, identificherai i bug nel codice e otterrai ai rispettivi sviluppatori di risolvere il problema e ripetere il test.

Se questo errore si verifica in un test di regressione, questo bug viene introdotto a causa di un nuovo sviluppo software fatto in cima alla base di codice esistente.

Questo dimostra che c’è qualcosa di sbagliato nella nuova base di codice che deve essere corretta per assicurarsi che la vecchia funzionalità funzioni. Ancora una volta, gli sviluppatori devono prendersene cura.

Che ne dici di avere molti casi di test? Diciamo che abbiamo TestCase1 e TestCase2, ognuno con diversi test.

È possibile creare quella che viene chiamata una suite di test ed eseguirla utilizzando un test runner come segue:

suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestCase1))
suite.addTest(unittest.makeSuite(TestCase2))
runner = unittest.TextTestRunner()
runner.run(suite)

Il codice sopra eseguirà tutti i test in TestCase1 e quindi in TestCase2.

Questo è tutto per oggi. Spero che aiuti.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.