Quest'ultimo test Python è il più complesso e pertanto potenzialmente il più ricco di insidie. Avremo a che fare con quattro pagine diverse del sito (login, bozza istantanea, pubblicazione dell'articolo e visualizzazione in homepage) in ognuna delle quali dovremo attendere l'apparizione di componenti con il rischio di incorrere nei relativi timeout.
Il test Python
Per lo svolgimento del test Python si è scelto di creare una funzione interna new_post
che si occupa di svolgere tutte le operazioni e verrà poi richiamata in un test. Il suo contributo sarà quello di portare alla pubblicazione di un post dal titolo 'Articolo di test' e il contenuto 'Questo articolo è stato scritto durante un test'.
Il contenuto di new_post
è suddiviso in più porzioni con dei commenti. Le sue parti iniziale e finale ci sono già note in quanto problematiche affrontate nelle lezioni precedenti (login e ricerca di un articolo) mentre quelle centrali sono delicate in quanto realizzano operazioni sequenziali, dipendenti l'una dall'altra: creazione della bozza e sua pubblicazione.
L'aspetto più delicato consiste probabilmente nel momento di pubblicazione della bozza in quanto dovremo premere due volte "Pubblica". Ciò viene offerto da due button diversi che, da un punto di vista umano, sembrano identici in quanto hanno stessa forma e colore sebbene il secondo appaia in un pannello che compare dalla destra. Tuttavia dal punto di vista del web testing vanno lavorati in maniera differente in quanto mentre il secondo appare, il primo risulta ancora presente nell'interfaccia e ciò crea una sorta di conflitto. Per tale motivo, abbiamo individuato il primo comodamente tramite etichetta con XPath, //button[text()="Pubblica"]
, mentre il secondo con un selettore CSS, button.editor-post-publish-button
. Per tali esplorazioni, l'uso della console del browser può risultare estremamente comoda!
Il codice
Vediamo il codice.
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
import unittest
class Testing(unittest.TestCase):
def setUp(self):
options = webdriver.ChromeOptions()
options.add_argument('--headless')
self.driver = webdriver.Chrome(options=options)
def new_post(self):
secondi=10
URL="http://172.19.0.3"
titolo_post='Articolo di test'
contenuto_post='Questo articolo è stato scritto durante un test'
# login
self.driver.get(f"{URL}/wp-admin")
username=self.driver.find_element(By.ID, "user_login")
password=self.driver.find_element(By.ID, "user_pass")
button=self.driver.find_element(By.ID, "wp-submit")
username.clear()
username.send_keys('studente')
password.clear()
password.send_keys('topolino')
button.click()
# attendiamo che appaia il form per le bozze rapide
titolo = WebDriverWait(self.driver, secondi).until(
EC.visibility_of_element_located((By.CSS_SELECTOR, "#title")))
# inseriamo i dati del post
title=self.driver.find_element(By.ID, "title")
content=self.driver.find_element(By.ID, "content")
save=self.driver.find_element(By.ID, "save-post")
title.clear()
title.send_keys(titolo_post)
content.clear()
content.send_keys(contenuto_post)
save.click()
# passiamo all'elenco degli articoli e troviamo la bozza creata
self.driver.get(f'{URL}/wp-admin/edit.php')
draft=WebDriverWait(self.driver, secondi).until(
EC.visibility_of_element_located((By.XPATH, f"//a[text() = '{titolo_post}']")))
draft.click()
# premiamo due volte il tasto "Pubblica" individuato in modi diversi
button= WebDriverWait(self.driver, secondi).until(
EC.visibility_of_element_located((By.XPATH, '//button[text()="Pubblica"]')))
button.click()
button= WebDriverWait(self.driver, secondi).until(
EC.visibility_of_element_located((By.CSS_SELECTOR, 'button.editor-post-publish-button')))
button.click()
# passiamo alla home del sito e cerchiamo il nostro articolo
self.driver.get(f'{URL}')
pubblicato= WebDriverWait(self.driver, secondi).until(
EC.visibility_of_element_located((By.XPATH, f"//a[text() = '{titolo_post}']")))
print(pubblicato.get_attribute('innerHTML'))
def test_create_post(self):
self.new_post()
def tearDown(self):
self.driver.quit()
if __name__ == '__main__':
unittest.main()
Esecuzione del codice
Nonostante l'aspetto più articolato dei precedenti, l'esecuzione porterà al responso a cui siamo abituati: riuscita del testcase o eventualmente numero di test falliti. In casi, del genere, con tempistiche che si sovrappongono conviene porre un adeguato tempo di timeout e, in caso di fallimento per il suo scadere, prolungarlo momentaneamente almeno per essere sicuri della riuscita del test.
Test Python di questo tipo sono importanti sebbene non devono essere gli unici da utilizzare. In quanto creare prima un certo numero di test unitari è importantissimo per studiare le singole funzionalità e verificarle: un test che ne integra diverse ha senso quando sappiamo che sulle singole possiamo contare.