いろは2986023 views
高校化学2913383 views
高校生物549842 views
教育148875 views
小学理科717236 views
数学講師2852771 views
Computer365120 views
高校日本史189857 views
高校物理158224 views
中学英語808712 views
Help
Tools

English

Flask のテスト戦略と pytest の活用

Flask アプリケーションのテストは pytest を使うと効率的に書ける。テストクライアント、フィクスチャ、モックを活用したテスト戦略を解説する。

基本的なテスト設定

# tests/conftest.py
import pytest
from app import create_app
from app.extensions import db

@pytest.fixture
def app():
    app = create_app('testing')
    with app.app_context():
        db.create_all()
        yield app
        db.drop_all()

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

@pytest.fixture
def runner(app):
    return app.test_cli_runner()

テストクライアントの使い方

# tests/test_views.py
def test_index(client):
    response = client.get('/')
    assert response.status_code == 200
    assert b'Welcome' in response.data

def test_login(client):
    response = client.post('/login', data={
        'username': 'alice',
        'password': 'secret'
    })
    assert response.status_code == 302  # リダイレクト

セッションを使ったテスト

def test_authenticated_access(client):
    with client.session_transaction() as sess:
        sess['user_id'] = 1
    
    response = client.get('/dashboard')
    assert response.status_code == 200

JSON API のテスト

def test_api_create_user(client):
    response = client.post('/api/users',
        json={'name': 'Alice', 'email': 'alice@example.com'},
        content_type='application/json'
    )
    assert response.status_code == 201
    data = response.get_json()
    assert data['name'] == 'Alice'

データベースを使ったテスト

# tests/conftest.py
@pytest.fixture
def sample_user(app):
    from app.models import User
    user = User(username='testuser', email='test@example.com')
    user.set_password('password')
    db.session.add(user)
    db.session.commit()
    return user

# tests/test_user.py
def test_user_login(client, sample_user):
    response = client.post('/login', data={
        'username': 'testuser',
        'password': 'password'
    })
    assert response.status_code == 302

モックの活用

from unittest.mock import patch

def test_send_email(client, sample_user):
    with patch('app.services.email_service.send_email') as mock_send:
        mock_send.return_value = True
        response = client.post('/reset-password', data={
            'email': 'test@example.com'
        })
        assert response.status_code == 200
        mock_send.assert_called_once()

カバレッジの計測

pip install pytest-cov
pytest --cov=app tests/

テストの構成

tests/
├── conftest.py           # 共通フィクスチャ
├── test_views.py         # ビューのテスト
├── test_api.py           # API のテスト
├── test_models.py        # モデルのテスト
├── test_services.py      # サービス層のテスト
└── test_integration.py   # 統合テスト

ファクトリを使ったテストデータ

# tests/factories.py
from app.models import User

class UserFactory:
    _counter = 0
    
    @classmethod
    def create(cls, **kwargs):
        cls._counter += 1
        defaults = {
            'username': f'user{cls._counter}',
            'email': f'user{cls._counter}@example.com'
        }
        defaults.update(kwargs)
        user = User(**defaults)
        db.session.add(user)
        db.session.commit()
        return user

pytest とフィクスチャを活用すれば、テストコードの重複を減らしつつ、包括的なテストを実現できる。