====== Python web test amb Pytest ======
{{ pytest_logo.svg?200|By Holger Krekel - https://pypi.org/project/pytest/, CC BY 2.5, https://commons.wikimedia.org/w/index.php?curid=116199948 }}
Referències:
* Continua de [[Python Web]] , cal conèixer Flask
* Necessitaràs [[Python venv]]
{{tag> #Daw #DawMpDual #DawMpProj #DawMp07Uf1 #DawMp07Uf02 #DawMp07Uf03 #DawMp07Uf04 #DawMp07Uf1 #DawMp07Uf02 #DawMp07Uf03 #DawMp07Uf04 #Ciber #CiberMp03 #Ceti #CetiMp03 python web flask test testing pytest }}
\\
Per poder seguir els exemples d'aquesta pàgina cal que abans hagis fet l'app bàsica amb el formulari que apareix a [[Python web]].
===== Pytest + client de tests de Flask =====
En aquesta primera aproximació **testejarem la webapp Flask amb un client intern de ''pytest'', és a dir, que no farà servir un //browser// real**.
Fem-li un cop d'ull a la [[https://flask.palletsprojects.com/testing/|documentació de test amb Flask]].
Primera cosa que cal fer, instal·lar el mòdul de tests ''pytest'':
(env) $ pip install pytest
Després, ens diuen que fem un **test skeleton**, però l'exemple que ens donen té una configuració avançada per posar a punt la base de dades, utilitzant una //app factory//, etc.
Nosaltres implementarem una versió simplificada sobre l'arxiu ''test_web.py''. Com podeu veure, **Flask disposa d'un client ''test_client''** que permet accedir als //endpoints// o rutes i comprovar els continguts rebuts mitjançant **assert**:
import pytest
from web import app
@pytest.fixture
def client():
with app.test_client() as client:
yield client
def test_landing_page(client):
rv = client.get('/')
assert b'Hello, World' in rv.data
Correm els tests amb la comanda ''pytest'':
(env) $ pytest
============================ test session starts =============================
platform linux -- Python 3.8.10, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: /home/enric/dev21/basicflask
collected 1 item
test_web.py . [100%]
============================= 1 passed in 0.09s ==============================
Com podem veure, ''pytest'' posa en marxa els tests dels arxius que comencen per ''test_'', i dins d'aquests, corre les funcions que també comencin per ''test_''.
\\
===== Pytest amb Selenium =====
[[Selenium]] és una llibreria per automatitzar la utilització d'un //browser// real.
Primer caldrà que instal·lem el package de pytest-selenium:
(env) $ pip install pytest-selenium
I també el driver per a automatitzar el Firefox:
$ sudo apt install firefox-geckodriver
Documentacions importants:
* [[https://pytest-selenium.readthedocs.io/en/latest/user_guide.html|Doc oficial de pytest-selenium]].
* [[https://selenium-python.readthedocs.io/|Doc oficial python-selenium]]
Posem aquí un test doble fonamental:
* A la //home page// comprovem que el text que apareix contingui "Hello, World"
* Al formulari d'exemple realitzat a [[Python Web]] utilitzem ''send_keys'' per escriure al camp de text i enviem el formulari localitzant el ''submit'' i clicant-lo.
import pytest
from selenium.webdriver.common.by import By
def test_home(selenium):
selenium.get('http://localhost:5000')
# podem examinar el què ens retorna el browser a "page_source"
assert "Hello, World" in selenium.page_source
def test_form(selenium):
# carreguem la pàgina del formulari
selenium.get('http://localhost:5000/formulari')
# busquem el quadre de text i hi escrivim un nom
elem = selenium.find_element(By.TAG_NAME,"input")
elem.send_keys("manolo")
# cerquem el botó de submit i el cliquem
submit = selenium.find_element(By.XPATH,"//input[@type='submit']")
submit.click()
# comprovem que el missatge de salutació contingui
# el nom introduit prèviament al formulari
assert "Salut, manolo" in selenium.page_source
Per posar en marxa el test ens caldrà 2 shells. En la 1a, posem en marxa la app:
(env) $ flask --app web run
I a la 2a shell engeguem els tests:
(env) $ pytest --driver Firefox
Fixa't en què per trobar elements fem servir ''find_element'' amb un ''By.XPATH''.
Pots trobar més info de com localitzar elements a la **doc oficial de Selenium per Python**:
* [[https://selenium-python.readthedocs.io/navigating.html|Secció Navigating]]
* [[https://selenium-python.readthedocs.io/api.html#locate-elements-by|Secció API]]
\\
===== Exercici : login =====
Pàgina de login de l'app:
* Crea un formulari que demani usuari i contrasenya. El formulari s'accedeix per mètode GET però envia les dades per mètode POST.
* Crea una pàgina (per POST) que respongui al formulari d'usuari i contrasenya. Crea un diccionari global amb noms d'usuari i contrasenyes vàlids (//hardcoded//).
* Assegura't que la pàgina de resposta al formulari respon amb un missatge que contingui un "OK" a la pàgina, i si el nom d'usuari és erroni respon adequadament amb un missatge que contingui "ERROR".
* **Comprova manualment el punt anterior. Abans de fer els tests automàtics cal fer-los manuals PER A TOTS ELS CASOS** (tant si funciona OK, com si dona error).
Testejant l'app.
* Examina [[https://flask.palletsprojects.com/en/1.1.x/testing/#logging-in-and-out|la secció "logging in and out" de la documentació dels tests]].
* Afegeix dues funcions de test que comprovin el següent:
- Que els usuaris i contrasenyes que has //hardcodejat// al codi es loguen correctament.
- Que una combinació usuari/contrasenya que no ha estat introduïda no funciona i dona el missatge d'error.
\\
===== Per saber més =====
En [[https://testdriven.io/blog/flask-pytest/|aquesta pàgina s'expliquen molts conceptes de testing en Flask i pytest]].