Cum să testezi un API Python cu pytest și requests
In this tutorial, you'll learn about Cum să testezi un API Python cu pytest și requests. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
Testarea API-ului asigură că endpoint-urile funcționează corect, gestionează erorile și returnează date în formatul așteptat. În acest ghid vei învăța cum să testezi un API Python cu pytest, requests și TestClient.
Problema
După fiecare modificare, trebuie să testezi manual endpoint-urile. Descoperi bug-uri abia în producție, iar refactorizările sunt riscante pentru că nu ai o plasă de siguranță.
Soluția Rapidă
1. Setup pentru teste
pip install pytest httpx requests
2. Testare cu TestClient (FastAPI)
from fastapi.testclient import TestClient
from main import app
client = TestClient(app)
def test_lista_produse():
response = client.get("/produse")
assert response.status_code == 200
assert isinstance(response.json(), list)
def test_creeaza_produs():
produs = {"nume": "Laptop", "pret": 3500}
response = client.post(
"/produse",
json=produs
)
assert response.status_code == 201
data = response.json()
assert data["nume"] == "Laptop"
def test_produs_negasit():
response = client.get("/produse/999")
assert response.status_code == 404
assert "eroare" in response.json()
def test_date_invalide():
response = client.post(
"/produse",
json={"nume": "", "pret": -10}
)
assert response.status_code == 422
3. Testare cu requests (Flask)
import requests
BASE_URL = "http://localhost:5000"
def test_lista_produse():
r = requests.get(f"{BASE_URL}/api/produse")
assert r.status_code == 200
assert len(r.json()) > 0
def test_creare_produs():
payload = {"nume": "Mouse", "pret": 150}
r = requests.post(
f"{BASE_URL}/api/produse",
json=payload
)
assert r.status_code == 201
assert r.json()["nume"] == "Mouse"
4. Testare cu pytest parametrizat
import pytest
@pytest.mark.parametrize("endpoint,expected_status", [
("/produse", 200),
("/produse/1", 200),
("/produse/999", 404),
("/utilizatori", 401), # endpoint protejat
])
def test_status_code(endpoint, expected_status):
response = client.get(endpoint)
assert response.status_code == expected_status
@pytest.mark.parametrize("payload,expected_status", [
({"nume": "Laptop", "pret": 3500}, 201),
({"nume": ""}, 422),
({"pret": "nu-e-numar"}, 422),
({}, 422),
])
def test_creare_produs_validare(payload, expected_status):
response = client.post("/produse", json=payload)
assert response.status_code == expected_status
5. Testare autentificare
def test_acces_fara_token():
response = client.get("/admin")
assert response.status_code == 401
def test_acces_cu_token():
# obține token
login_r = client.post(
"/login",
data={"username": "admin", "password": "parola"}
)
token = login_r.json()["access_token"]
# folosește token-ul
response = client.get(
"/admin",
headers={"Authorization": f"Bearer {token}"}
)
assert response.status_code == 200
6. Fixtură pentru setup
@pytest.fixture
def date_test():
"""Populează baza de date cu date de test"""
client.post("/produse", json={"nume": "Laptop", "pret": 3500})
client.post("/produse", json={"nume": "Mouse", "pret": 150})
yield
client.delete("/test/reset") # curăță după test
def test_cauta_produs(date_test):
response = client.get("/produse?cauta=laptop")
assert len(response.json()) > 0
7. Test în bandă (CI/CD)
Creează fișierul .github/workflows/test.yml:
name: Testare API
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: pip install -r requirements.txt
- run: pytest --cov=app tests/
Rulează toate testele:
pytest tests/ -v --cov=app
Output:
tests/test_api.py::test_lista_produse PASSED
tests/test_api.py::test_creeaza_produs PASSED
tests/test_api.py::test_produs_negasit PASSED
tests/test_api.py::test_date_invalide PASSED
Prevenție
- Rulează testele înainte de fiecare commit
- Menține o acoperire a codului de minim 80%
- Testează atât scenariile de succes, cât și pe cele de eroare
- Folosește o bază de date de test separată
- Rulează testele în pipeline-ul CI/CD
Greșeli Comune
- Testarea doar a căii fericite -- nu testa și scenariile de eroare (404, 422, 500)
- Teste care depind de ordinea de execuție -- fiecare test trebuie să fie independent
- Ignorarea timeout-urilor -- testele pentru endpoint-uri lente trebuie să aibă timeout configurat
- Teste cu date hardcodate -- folosește fixturi și date dinamice
- Fără curățare după teste -- datele de test poluează baza de date
Exercițiu Practic
Scrie un set complet de teste pentru un API CRUD de comenzi: testează crearea, listarea, actualizarea, ștergerea, validarea datelor și autentificarea. Include test parametrizat pentru cel puțin 5 cazuri de eroare.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro