Dopo aver tanto studiato, cerchiamo di mettere alla prova le nostre conoscenze con test automatici in Python sviluppati su una reale piattaforma di contenuti. Scegliamo uno dei CMS più utilizzati al mondo ovvero WordPress e pianifichiamo un testcase di tre test.
Test su WordPress con Python in locale
Diciamo subito che stiamo utilizzando una versione di prova del CMS appositamente installata su una macchina locale. Si tratta di un'installazione del tutto base che sfrutta il tema preimpostato ovvero Twenty Twenty four. Tutte le ricerche di elementi che condurremo saranno finalizzate alle prove che vogliamo svolgere ma anche indotte dalla struttura della nostra pagina. Quindi per riprodurre questi esperimenti sulla propria applicazione web si dovranno apportare eventuali modifiche a query XPath e selettori CSS compatibilmente con il tema ed i propri contenuti.
Per comodità abbiamo avviato un sito WordpPress mediante Docker Compose che ha permesso l'attivazione di due container, uno per il database ed uno per lo strato web.
Qualora si fosse interessati a seguire questa modalità (in alternativa, si può predisporre il tutto in locale o remoto seguendo la via che si preferisce) si può ricorrere ad esempi riportati in documentazione o utilizzare un semplice file YAML come il seguente. Privo di port forwarding e di volume ma sufficiente a lanciare i container ed impostare parole chiave:
version: "3"
services:
db:
image: mysql:5.7
restart: always
environment:
MYSQL_ROOT_PASSWORD: topolino
MYSQL_DATABASE: mywpdb
MYSQL_USER: mywpdbuser
MYSQL_PASSWORD: topolino
wordpress:
depends_on:
- db
image: wordpress:latest
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: mywpdbuser
WORDPRESS_DB_PASSWORD: topolino
WORDPRESS_DB_NAME: mywpdb
Per svolgere i test, dovendo accedere all'area di amministrazione, si dovrà utilizzare le credenziali utente create: nei nostri esempi l'utente avrà nome studente e la password sarà topolino. L'indirizzo web riportato, sempre in riferimento alla nostra installazione, sarà 172.19.0.3.
Pianificare il testcase Python
Nei nostri test, svolgeremo tre tipi di attività di complessità crescente:
- verificare la presenza di uno specifico post nella homepage. Supporremo di essere interessati a verificare che tra i vari post presenti nella pagina ve ne sia uno con un titolo in particolare. Questo ci permetterà di assodare la corretta visualizzazione della homepage e della sezione relativa ai post;
- effettuare login fornendo dinamicamente le credenziali e verificando che appaia la sezione "Bacheca". Segno che siamo entrati con successo nel backend. Già si tratta di un qualcosa di un po' più articolato, dove interagiremo con un form, invieremo dei dati (le credenziali) e verificheremo la risposta;
- creare un nuovo post da zero. Questo è il test più "di integrazione" in assoluto. Seguirà i seguenti sottopassaggi:
- faremo login;
- cercheremo il form per la creazione di una bozza istantanea e la salveremo immettendo titolo e contenuto;
- entreremo nella pagina della gestione bozze, apriremo quella appena creata e la pubblicheremo;
- andremo in homepage e verificheremo la presenza dell'articolo creato.
Tutti i test potrebbero far parte di un unico testcase ma per comodità di lettura li sviluppiamo ognuno in un testcase a sé stante. Abbiamo usato in ogni caso unittest
, anche per i test di integrazione (ricordiamo che WordPress in ogni caso richiama il database), visto che è lo strumento che abbiamo conosciuto in questa guida. Vedremo che sarà pienamente all'altezza e rimandiamo ogni eventuale approfondimento su altri framework a future ricerche on line.
Primo test: post pubblicato
Iniziamo con il primo test. Quello che consiste nella verifica della presenza di uno specifico articolo nella homepage. Come vedremo nei prossimi esempi, la gestione del waiting per attendere l'apparizione delle componenti è fondamentale. Sarebbe saggio farne uso anche qui ma per semplicità, in questo primo esempio, ovvieremo.
La nostra sezione post appare così nella homepage (abbiamo popolato il blog con alcuni articoli di prova):
Analizzando gli elementi della pagina scopriamo che ogni titolo di un articolo è costituito da un elemento h2
di classe wp-block-post-title
che contiene un link. Il testo presente nel link corrisponde al titolo dell'articolo.
Possiamo seguire vari approcci ma quello che preferiamo consiste nel recuperare tutti gli elementi che rispondano al selettore CSS h2.wp-block-post-title a
. Per poi trasportare tutti i titoli recuperati in una lista Python ed eseguire il test di presenza dell'articolo che cerchiamo con il metodo assertIn
. Analogamente a ciò che fa l'operatore in
,
esso verifica se un elemento è presente in una lista. Noi cercheremo l'articolo intitolato "Algoritmo per la felicità":
from selenium import webdriver
from selenium.webdriver.common.by import By
import unittest
class Testing(unittest.TestCase):
def setUp(self):
options = webdriver.ChromeOptions()
options.add_argument('--headless')
self.driver = webdriver.Chrome(options=options)
self.driver.get("http://172.19.0.3")
def test_find_post(self):
to_find="h2.wp-block-post-title a"
posts=self.driver.find_elements(By.CSS_SELECTOR, to_find)
self.assertIn("Algoritmo per la felicità", [p.text for p in posts])
def tearDown(self):
self.driver.quit()
if __name__ == '__main__':
unittest.main()
Come si vede, ci siamo collegati alla homepage del sito e abbiamo richiesto di elencarci tutto ciò che corrisponde a h2.wp-block-post-title a
. La query ha fornito una sequenza di elementi web corrispondenti ognuno ad un link. Perciò, con una list comprehension [p.text for p in posts]
, abbiamo estratto una lista di stringhe composta da tutti i titoli.
Fatto ciò, siamo passati a verificare la presenza del titolo di nostro interesse.
Una volta eseguito il test, abbiamo ricevuto la comunicazione che esso ha avuto successo pertanto l'homepage è stata visualizzata correttamente ed il titolo è stato trovato:
.
----------------------------------------------------------------------
Ran 1 test in 2.018s
OK
Test di controprova
Soprattutto quando si è alle prime esperienze conviene sempre fare la prova contraria cercando, ad esempio, un titolo che non esiste sia per abituarci alla lettura degli errori sia per ricevere ulteriori informazioni sul test tramite l'output mostrato.
Nel seguente caso, abbiamo lanciato il test cercando un post non esistente, "Leggere libri è importante", e questa è stata la comunicazione dell'errore:
F
======================================================================
FAIL: test_find_post (__main__.Testing)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/ai/webtest/wppost.py", line 16, in test_find_post
self.assertIn("Leggere libri è importante", [p.text for p in posts])
AssertionError: 'Leggere libri è importante' not found in ['Vorrei inventare una nuova macchina', 'Siete mai stati a Budapest?', 'Algoritmo per la felicità']
----------------------------------------------------------------------
Ran 1 test in 2.017s
FAILED (failures=1)
Su un test eseguito, uno è fallito. Però al contempo abbiamo ricevuto conferma che l'elenco dei titoli è stato trasposto nella lista di stringhe ['Vorrei inventare una nuova macchina', 'Siete mai stati a Budapest?', 'Algoritmo per la felicità']
, correttamente corrispondente all'elenco di post pubblicati.
Per semplicità abbiamo supposto che non ci fossero paginazioni e tutti gli elementi si trovassero nella stessa pagina: probabilmente in un blog popolato da molti contenuti dovremmo tenere conto di questo limitandoci agli ultimi usciti o estendendo la ricerca nelle pagine degli articoli più datati.