Il talk di Fiorella "Scrivere i primi test frontend con Python? Si può!"

Front end testing con Selenium e Splinter

C’è una parte del processo di development che non è particolarmente amata dagli sviluppatori: quella di testing. Per quanto “antipatici”, i test fanno parte degli step più importanti per la realizzazione di software perché permettono di verificare se le applicazioni e i siti web in produzione sono funzionanti in tutte le loro parti, quali sono le mancanze da colmare e le feature da rivedere. 

Tra i test che consentono di provare la solidità del software prodotto ci sono anche quelli relativi al front end. Si tratta di test specifici per l’interfaccia grafica (GUI) che,oltre a verificare le funzionalità delle app e dei siti web, permettono di analizzare anche gli aspetti di accessibilità ed usabilità. Eseguire questo tipo di verifiche manualmente richiede molto tempo ed è per questo che i developer si avvalgono di strumenti per l’automazione. Ho sperimentato in prima persona le criticità del q/a front end perchè in Nephila mi occupo di eseguire questo tipo di test. Nel talk che ho portato a PyCon X, conferenza tenutasi a Firenze, ho parlato di due tool che ho utilizzato per svolgere la mia attività e che vedremo ora nel dettaglio.

SELENIUM

Inizialmente mi sono approcciata al front end testing attraverso Selenium, una suite di test automatizzata per le applicazioni web, che è composta da quattro elementi: 

  • Selenium Integrated Development Environment (IDE)
  • Selenium Remote Control (RC)
  • WebDriver
  • Selenium Grid

In particolare ho cominciato con Selenium IDE, un plugin open source che permette di creare dei test case registrando le azioni che gli utenti eseguono all’interno di un browser. Questo strumento è di facile installazione perché può essere aggiunto come estensione del browser (nel caso in cui si scelga di utilizzarlo su Firefox sarà necessario avvalersi anche del supporto di geckodriver affinché il tool funzioni correttamente). In passato Selenium IDE consentiva anche di estrarre dei test case in Python ma l’ultima release ha reso difficile questo tipo di operazione. L’interfaccia è intuitiva e presenta dei comandi per l’esecuzione dei test, un tasto che permette di registrare, una finestra per l’inserimento dei comandi e una finestra di log e reference.

interfaccia Selenium IDE

Tra i comandi più utilizzati ci sono i seguenti:

  • open - che permette di aprire una pagina
  • click - per comunicare allo strumento di cliccare un oggetto della pagina
  • type - che consente di inserire i valori nella text area
  • select - che viene usato per selezionare un valore
  • store - per salvare una variabile

Quando registra le azioni dell’utente sul browser, Selenium IDE è in grado di segnalare dove e in che momento lo user clicca, digita, fa un mouse over o sposta il mouse da qualsiasi elemento della pagina testata (un bottone, un link, un form ecc).

Nell’esempio pratico portato al talk ho chiesto a Selenium IDE di aprire il browser, effettuare una ricerca sulla barra degli indirizzi, ovvero di digitare il testo Django documentation e di cliccare su un risultato. I comandi che ho utilizzato sono questi

Esempio con Selenium IDE

Splinter

Come anticipato in precedenza, con le ultime versioni Selenium IDE rende più difficile l’estrazione di test case in Python e questo è uno dei motivi per cui ho deciso di passare a Splinter. Splinter èuno strumento per testare le applicazioni web con Python che consente di automatizzare le azioni del browser, di visitare gli URL e di interagire con i loro elementi. Rispetto a Selenium IDE, Splinter è più vantaggioso perché ha una sintassi più snella che permette di semplificare la scrittura dei test. Per fare un esempio ecco il codice necessario per comunicare a Selenium IDE come trovare un elemento all’interno del browser:

elem = browser.find_element.by_name('name')
elem.send_keys('molly')


Questo invece è il codice che bisogna scrivere affinchè Splinter esegua la stessa azione

browser.fill('name', 'molly')


Anche Splinter è un tool open source. Inoltre è supportato dalla maggior parte dei browser (eccezione fatta per internet explorer), ha delle API semplici ed intuitive ed è di facile installazione. Per poterlo installare basterà digitare nel prompt dei comandi

$ pip install splinter

Esempio pratico

from splinter import Browser

with Browser() as browser:
 # Visit URL
 url = "http://www.google.com"
 browser.visit(url)
 browser.fill('q', 'Django documentation')
 # Find and click the 'search' button
 browser.find_by_name('btnK').click()

 if browser.is_text_present('https://docs.djangoproject.com/en/2.1/'):
 print("Yes, the official website was found!")
 else:
 print("No, it wasn't found. :( )")


Prendiamo in esame un caso molto semplice, un utente che esegue una ricerca su Google, accede un sito e naviga per trovare una risorsa, nello specifico la documentazione Django. Per poter eseguire un test è necessario importare il browser in Splinter e inizializzarlo. In questo momento è possibile indicare allo strumento che browser utilizzare e se non viene esplicitato nulla, il tool sceglie come predefinito Firefox. Per visitare il sito web si utilizzerà il metodo browser.visit in questo modo:

url = "http://www.google.com"
browser.visit(url)


Una volta caricata la pagina è possibile far eseguire a Splinter altri comandi come il clic,
l'inserimento di testo, ecc. Nell’esempio ho comunicato a Splinter di verificare se è presente un testo e, in caso di esito positivo, di stampare "Yes, the official website was found!"

ESEMPIO UNIT TEST

Splinter si può integrare anche negli unit test. Per farlo è necessario creare una classe, che nel caso specifico si chiama SplinterTest, definire un metodo (per l’esempio sottostante è stato definito il metodo test_django_docs) e degli assert. In particolare ho indicato a Splinter di comunicarmi se fosse presente il testo https://docs.djangoproject.com/en/2.1/.  Il codice per far funzionare il test è il seguente 

from splinter import Browser
from unittest import TestCase

class SplinterTest(TestCase):
 def test_django_docs(self):
 	with Browser() as browser:
 # Visit URL
 url = "http://www.google.com"
 browser.visit(url)
browser.fill('q', 'Django documentation')
 # Find and click the 'search' button
 browser.find_by_name('btnK').click()
self.assertTrue(browser.is_text_present('https://docs.djangoproject.com/en/2.1/'))
 	self.assertFalse(browser.is_text_present('https://docs.djangoproject.com/en/2.0/'))


Splinter è uno strumento molto interessante, è veloce (in termini di tempi per lo sviluppo) ed è semplice da utilizzare, per cui, nel caso in cui dobbiate occuparvi del front end testing ve lo consiglio!