⏱️4 min read · 749 words
pytest হল 2026 সালে পাইথন পরীক্ষার জন্য সোনার মান। Django, FastAPI, NumPy এবং হাজার হাজার ওপেন-সোর্স প্রকল্প দ্বারা ব্যবহৃত, pytest লেখা এবং চলমান পরীক্ষাগুলিকে স্বজ্ঞাত এবং শক্তিশালী করে তোলে। এই সম্পূর্ণ নির্দেশিকা আপনাকে আপনার প্রথম পরীক্ষা থেকে উন্নত ফিক্সচার, প্যারামেট্রিজ এবং সিআই ইন্টিগ্রেশনে নিয়ে যায়।
📋 Table of Contents
কেন ইউনিটেস্ট ওভার pytest?
- সহজ সিনট্যাক্স– সমতল
assertসহায়ক ব্যর্থতার বার্তা সহ বিবৃতি - শক্তিশালী ফিক্সচার– স্বয়ংক্রিয় টিয়ারডাউন সহ নির্ভরতা ইনজেকশন
- প্যারামেট্রিজ– অনেক ইনপুট সহ একটি পরীক্ষা চালান
- সমৃদ্ধ প্লাগইন ইকোসিস্টেম— কভারেজ, xdist, মক, asyncio, এবং আরও অনেক কিছু
- আরও ভালো আবিষ্কার– বয়লারপ্লেট ছাড়াই স্বয়ংক্রিয়ভাবে পরীক্ষাগুলি খুঁজে পায়
ইনস্টলেশন এবং প্রথম পরীক্ষা
# Install pytest
pip install pytest pytest-cov pytest-asyncio
# Create a test
# test_math.py
def add(a, b):
return a + b
def test_add():
assert add(2, 3) == 5
assert add(-1, 1) == 0
assert add(0, 0) == 0
# Run tests
pytest # run all tests
pytest test_math.py # specific file
pytest -v # verbose output
pytest -k "add" # run tests matching name
pytest --tb=short # shorter tracebacks
পরীক্ষা সংস্থা
# Recommended structure
# tests/
# conftest.py — shared fixtures
# test_users.py
# test_orders.py
# integration/
# test_api.py
# unit/
# test_services.py
# pytest.ini or pyproject.toml
# [tool.pytest.ini_options]
# testpaths = ["tests"]
# addopts = "-v --tb=short"
# Test class grouping
class TestUserService:
def test_create_user(self):
user = create_user("alice@example.com")
assert user.email == "alice@example.com"
def test_create_user_invalid_email(self):
with pytest.raises(ValueError, match="Invalid email"):
create_user("not-an-email")
def test_duplicate_email_raises(self, db):
create_user("alice@example.com")
with pytest.raises(DuplicateError):
create_user("alice@example.com")
ফিক্সচার – pytest এর সুপার পাওয়ার
import pytest
from app.database import Database
from app.models import User
# Simple fixture
@pytest.fixture
def sample_user():
return User(id=1, name="Alice", email="alice@example.com")
# Fixture with setup and teardown
@pytest.fixture
def db():
database = Database(url="sqlite:///:memory:")
database.create_tables()
yield database # test runs here
database.drop_tables() # teardown
# Session-scoped fixture — runs once per test session
@pytest.fixture(scope="session")
def app_client():
from app import create_app
app = create_app(testing=True)
return app.test_client()
# Fixture using other fixtures
@pytest.fixture
def admin_user(db):
user = db.create_user(email="admin@test.com", role="admin")
return user
# conftest.py — shared fixtures auto-discovered
# pytest finds conftest.py automatically
প্যারামেট্রিজ — একাধিক ক্ষেত্রে পরীক্ষা করুন
import pytest
def is_valid_email(email: str) -> bool:
import re
return bool(re.match(r"[^@]+@[^@]+\.[^@]+", email))
@pytest.mark.parametrize("email,expected", [
("alice@example.com", True),
("user+tag@domain.co.uk", True),
("invalid", False),
("no-at-sign", False),
("@nodomain.com", False),
("user@.com", False),
("", False),
])
def test_email_validation(email, expected):
assert is_valid_email(email) == expected
# Multiple parametrize decorators — creates cartesian product
@pytest.mark.parametrize("base", [2, 10, 16])
@pytest.mark.parametrize("exp", [1, 2, 3])
def test_powers(base, exp):
result = base ** exp
assert result == pow(base, exp)
পাইটেস্ট-মক দিয়ে উপহাস করা
pip install pytest-mock
import pytest
from app.services import UserService
from app.email import EmailSender
def test_registration_sends_welcome_email(mocker):
# Mock the email sender
mock_send = mocker.patch("app.services.EmailSender.send")
service = UserService()
service.register("alice@example.com", "securepass")
# Assert email was sent
mock_send.assert_called_once_with(
to="alice@example.com",
subject="Welcome to TechPulse!"
)
def test_external_api_timeout(mocker):
# Mock requests.get to simulate timeout
mocker.patch(
"requests.get",
side_effect=requests.exceptions.Timeout
)
with pytest.raises(ServiceUnavailableError):
fetch_weather("London")
# Spy on real method (calls real code but tracks calls)
def test_cache_used_on_second_call(mocker):
spy = mocker.spy(cache_service, "get")
fetch_user(1)
fetch_user(1) # should hit cache
assert spy.call_count == 2
Async কোড পরীক্ষা করা হচ্ছে
pip install pytest-asyncio
import pytest
import pytest_asyncio
# Mark entire file as async
# pytest.ini: asyncio_mode = auto
@pytest.mark.asyncio
async def test_async_fetch():
async with AsyncClient(app=app, base_url="http://test") as client:
response = await client.get("/api/users")
assert response.status_code == 200
# Async fixture
@pytest_asyncio.fixture
async def async_db():
async with AsyncDatabase() as db:
await db.create_tables()
yield db
await db.drop_tables()
কভারেজ রিপোর্টিং
# Run with coverage
pytest --cov=app --cov-report=html --cov-report=term-missing
# Output:
# Name Stmts Miss Cover
# app/models.py 45 3 93%
# app/services.py 87 12 86%
# TOTAL 132 15 89%
# Fail if coverage below threshold
pytest --cov=app --cov-fail-under=80
# .coveragerc or pyproject.toml
# [tool.coverage.run]
# omit = ["*/tests/*", "*/migrations/*"]
pytest মার্কস – পরীক্ষা শ্রেণীবদ্ধ করুন
import pytest
# Define marks in pyproject.toml
# [tool.pytest.ini_options]
# markers = [
# "slow: marks tests as slow",
# "integration: marks integration tests",
# "unit: marks unit tests",
# ]
@pytest.mark.slow
@pytest.mark.integration
def test_full_user_registration_flow(client, db):
# End-to-end registration test
response = client.post("/register", json={
"email": "test@example.com",
"password": "SecurePass123!"
})
assert response.status_code == 201
assert db.users.count() == 1
# Run only unit tests
# pytest -m unit
# Skip slow tests in CI
# pytest -m "not slow"
গিটহাব অ্যাকশন সিআই ইন্টিগ্রেশন
# .github/workflows/test.yml
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11", "3.12"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
pip install uv
uv pip install -e ".[dev]" --system
- name: Run tests
run: pytest --cov=app --cov-fail-under=80
- name: Upload coverage
uses: codecov/codecov-action@v4
pytest আয়ত্ত অনুশীলন নেয় কিন্তু লভ্যাংশ প্রদান করে. বৈশিষ্ট্যগুলির (TDD) পাশাপাশি পরীক্ষাগুলি লিখুন, সেটআপ/টিয়ারডাউনের জন্য ফিক্সচার ব্যবহার করুন, প্রান্তের ক্ষেত্রে প্যারামেট্রিজ করুন এবং বহিরাগত নির্ভরতাকে উপহাস করুন। ব্যবসায়িক যুক্তিতে 80%+ কভারেজ এবং 100% সমালোচনামূলক পথে লক্ষ্য করুন।
🔗 Share this article
✍️ Leave a Comment