Imparare a interagire con i form rappresenta al contempo qualcosa di molto utile nella pratica professionale ed un esercizio estremamente completo mentre si fa esperienza con Python e Selenium. Il motivo della prima affermazione è che i form costituiscono uno degli elementi più comuni delle pagine web e sono il vettore principale dell'immissione dati. Ogni volta che usando un servizio on line cerchiamo un appartamento in affitto, prenotiamo un treno o richiediamo informazioni, stiamo compilando un form allo scopo di inviare dati ad un sito web facendo quella che - più tecnicamente per chi è avvezzo ai protocolli di rete - è in genere una richiesta HTTP POST.
Si tratta però anche di un esercizio completo nel percorso di apprendimento con Selenium in quanto mette in moto una serie di skill che abbiamo acquisito sinora:
- ricerca di elementi nell'interfaccia web sfruttando tecniche già incontrate come XPath, selettori CSS, id, etc.
- immissione di input nei campi del form;
- invio dei dati o interazione mediante click di pulsanti;
- lettura di risultati ancora passando per l'individuazione delle componenti.
Avviamoci con un esempio pratico.
Form e Web testing in Python
Il form che andiamo a predisporre contiene due campi di testo che accettano numeri ed un pulsante al cui click viene eseguita la divisione tra i valori in essi inseriti:
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
</head>
<body>
<form>
<label for="dividendo">Dividendo</label><br>
<input type="number" id="dividendo" name="dividendo"><br>
<label for="divisore">Divisore</label><br>
<input type="number" id="divisore" name="divisore"><br><br>
<button type="button">Calcola</button>
</form>
<br>
<div id="risultato"></div>
<script>
$(document).ready(function(){
$("button").click(function(){
if ($("#divisore").val()==0)
alert("Errore: divisione per zero!")
else
$("#risultato").text($("#dividendo").val()/$("#divisore").val())
});
});
</script>
</body>
</html>
Come è prevedibile, è fondamentale che il secondo campo, dedicato all'immissione del divisore, non contenga il valore zero pena un errore all'atto della divisione. Il nostro test sarà quindi focalizzato sull'immissione di valori e l'esecuzione stando attenti che questa non porti ad un errore. Se, al momento del click, si ha un valore nullo nel divisore la pagina web produce un alert con un messaggio di errore pertanto il nostro compito sarà quello di scrivere operazioni automatiche per:
- immettere i valori;
- eseguire il click sul
button
senza controllare il valore del divisore (dobbiamo eseguire test seguendo il normale flusso di lavoro di un utente); - attendere l'apparizione di un alert oppure leggere il risultato della divisione.
Il test
Una volta attivato il driver (si potrà scegliere il browser che si predilige) invocheremo la pagina web che nel nostro caso sarà resa disponibile su un server locale alla porta TCP/80
. Per conferire omogeneità al test, scriviamo una funzione che riceve il driver (già connesso alla pagina) e nell'ordine:
- immette valori nei campi mediante il metodo
send_keys
; - esegue la pressione del pulsante con il metodo
click
; - grazie a quanto appreso a proposito di waiting si mette in attesa dell'apparizione di un alert. Se tale evento non si verificherà in un lasso di tempo (che noi imposteremo a 3 secondi) scatterà un timeout che sarà rilevato con il costrutto
try...except
.
def test_form(driver, valore_dividendo, valore_divisore):
# recupero elementi del form
dividendo=driver.find_element(By.ID, "dividendo")
divisore=driver.find_element(By.ID, "divisore")
calcola=driver.find_element(By.TAG_NAME, "button")
# immissione dati
dividendo.send_keys(valore_dividendo)
divisore.send_keys(valore_divisore)
# click sul pulsante
calcola.click()
# attesa alert
try:
WebDriverWait(driver, 3).until(EC.alert_is_present())
# alert apparso: ne recuperiamo il testo
alert = driver.switch_to.alert
messaggio=alert.text
alert.accept()
return False, messaggio
except TimeoutException:
# timeout scaduto => alert non apparso...Divisione valida: leggiamo il risultato
risultato=driver.find_element(By.ID, "risultato")
return True, risultato.text
La funzione Python restituirà due risultati di cui il primo servirà a capire se l'operazione ha avuto successo ed il secondo l'output che abbiamo ottenuto. Se eseguiamo la seguente invocazione:
driver.get('http://localhost/form.html')
print(test_form(driver, 84, 5))
otteniamo (True, '16.8')
dove 16.8 è il risultato ottenuto dalla divisione in quanto operazione valida mentre con:
driver.get('http://localhost/form.html')
print(test_form(driver, 84, 0))
otteniamo (False, 'Errore: divisione per zero!')
dove il secondo elemento è il messaggio comparso nell'alert.