Python / Тест бичих (pytest)

Тест бичих (pytest)

Код бичих нь зөвхөн ажиллуулж харахад хангалтгүй — шинэ өөрчлөлт хийхэд өмнөх зүйл эвдрэхгүй гэдгийг хэрхэн баталгаажуулах вэ? Автомат тест нь үүний хариулт. pytest нь Python-д хамгийн алдартай тест framework бөгөөд суралцахад хялбар, хүчирхэг.

pytest суулгах ба анхны тест

bash
pip install pytest

Тест файлын нэр test_ угтвараар эхэлнэ, тест функц ч мөн адил:

python
# test_тооцоолол.py

def нэмэх(а, б):
    return а + б

def хасах(а, б):
    return а - б

def test_нэмэх_эерэг():
    assert нэмэх(3, 5) == 8

def test_нэмэх_сөрөг():
    assert нэмэх(-2, -3) == -5

def test_хасах():
    assert хасах(10, 4) == 6

def test_нэмэх_тэг():
    assert нэмэх(0, 0) == 0
bash
# Бүх тест ажиллуулах
pytest

# Дэлгэрэнгүй гаралттай
pytest -v

assert нь нөхцөлийг шалгана — худал бол тест унана, pytest алдааг тайлбарлана. Ажиллуулахад иймэрхүү харагдана:

код
test_тооцоолол.py ....           [100%]
4 passed in 0.02s

Алдаа гарахыг тест хийх

Зарим тохиолдолд функц алдаа өгөх ёстой — үүнийг ч тест хийж болно:

python
# test_хуваах.py
import pytest

def хуваах(а, б):
    if б == 0:
        raise ValueError("Тэгд хуваах боломжгүй")
    return а / б

def test_хуваах_энгийн():
    assert хуваах(10, 2) == 5.0

def test_хуваах_тэгд():
    with pytest.raises(ValueError, match="Тэгд хуваах боломжгүй"):
        хуваах(10, 0)

def test_хуваах_бутархай():
    assert хуваах(7, 2) == pytest.approx(3.5)

pytest.raises() нь тухайн алдаа гарахыг баталгааждаг. pytest.approx() нь бутархай тоог ойролцоогоор шалгана — 0.1 + 0.2 == 0.3 Python-д False байдаг тул энэ чухал.

FastAPI endpoint тест хийх

httpx пакеж ашиглан FastAPI endpoint-ийг бодит server ажиллуулалгүй шууд тест хийнэ:

bash
pip install httpx
python
# test_api.py
from fastapi.testclient import TestClient
from main import app

client = TestClient(app)

def test_эхлэл_хуудас():
    хариу = client.get("/")
    assert хариу.status_code == 200
    assert "мэндчилгээ" in хариу.json()

def test_сурагч_үүсгэх():
    хариу = client.post("/сурагч", json={
        "нэр": "Болд",
        "и_мэйл": "bold@example.mn"
    })
    assert хариу.status_code == 201
    өгөгдөл = хариу.json()
    assert өгөгдөл["нэр"] == "Болд"
    assert "id" in өгөгдөл

def test_байхгүй_сурагч():
    хариу = client.get("/сурагч/99999")
    assert хариу.status_code == 404

TestClient нь бодит HTTP хүсэлт илгээдэггүй — санах ойд шууд ажилладаг тул маш хурдан.

fixture — ашиглагдах өгөгдөл бэлтгэх

Олон тестэд нэг ижил өгөгдөл хэрэгтэй үед @pytest.fixture ашиглана:

python
import pytest
from fastapi.testclient import TestClient
from main import app

@pytest.fixture
def client():
    return TestClient(app)

@pytest.fixture
def бүртгэлтэй_сурагч(client):
    хариу = client.post("/сурагч", json={
        "нэр": "Тест сурагч",
        "и_мэйл": "test@example.mn"
    })
    return хариу.json()

def test_сурагч_авах(client, бүртгэлтэй_сурагч):
    id = бүртгэлтэй_сурагч["id"]
    хариу = client.get(f"/сурагч/{id}")
    assert хариу.status_code == 200
    assert хариу.json()["нэр"] == "Тест сурагч"

def test_xp_нэмэх(client, бүртгэлтэй_сурагч):
    id = бүртгэлтэй_сурагч["id"]
    хариу = client.patch(f"/сурагч/{id}/xp")
    assert хариу.status_code == 200

Fixture нь тест бүрт дахин ажиллана — тестүүд бие биеэс хамаарахгүй, тусдаа байна. Тест бичих дадал эхэндээ хэцүү санагдаж болох боловч кодын чанарыг эрс сайжруулдаг — мэргэжлийн хөгжүүлэгч бүр ашигладаг арга.

Дараагийн хичээлд:

Async Python үндэсasync/await хэрхэн ажилладаг, яагаад FastAPI async-д суурилдаг, олон ажлыг зэрэгцүүлэн гүйцэтгэх аргыг сурна.