高校倫理1434270 views
雑学1472774 views
中学理科1627080 views
中学英語809228 views
LaTeX957931 views
高校日本史189949 views
小学算数1196005 views
MathPython492451 views
小学社会308820 views
ヒストリア285028 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 とフィクスチャを活用すれば、テストコードの重複を減らしつつ、包括的なテストを実現できる。