「何を作るか」を先に仕様として書き、仕様を実行可能にする。
TDDが「テスト」を先に書くなら、仕様駆動は「仕様」を先に書く。テストは仕様の一部。
| 対象 | |
|---|---|
| ✅ | 要件が明確なAPI開発(OpenAPI spec → 実装) |
| ✅ | 外部システムとのインターフェース設計 |
| ✅ | データ形式が決まっている処理(JSON Schema → バリデーション) |
| ❌ | 要件が不確定で試行錯誤が必要な段階 |
| ❌ | UIの見た目を探っている段階 |
# specs/api.yaml — まず仕様を書く
openapi: "3.0.0"
info:
title: Reservation API
version: "1.0"
paths:
/reservations:
post:
summary: 予約を作成
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [guest_name, party_size, date]
properties:
guest_name: { type: string, minLength: 1 }
party_size: { type: integer, minimum: 1, maximum: 20 }
date: { type: string, format: date }
responses:
"201":
description: 作成成功
content:
application/json:
schema:
type: object
properties:
id: { type: string }
status: { type: string, enum: [pending] }
from pydantic import BaseModel, Field
from datetime import date
class CreateReservationRequest(BaseModel):
guest_name: str = Field(min_length=1)
party_size: int = Field(ge=1, le=20)
date: date
class ReservationResponse(BaseModel):
id: str
status: str
# テスト(仕様に基づく)
def test_create_reservation_success(client: TestClient):
response = client.post("/reservations", json={
"guest_name": "田中",
"party_size": 4,
"date": "2026-06-01",
})
assert response.status_code == 201
data = response.json()
assert "id" in data
assert data["status"] == "pending"
def test_create_reservation_invalid_party_size(client: TestClient):
response = client.post("/reservations", json={
"guest_name": "田中",
"party_size": 0, # 仕様: minimum: 1
"date": "2026-06-01",
})
assert response.status_code == 400 # 仕様: 400エラー
// schemas/reservation.ts — 仕様をZodスキーマで定義
import { z } from "zod";
export const CreateReservationSchema = z.object({
guest_name: z.string().min(1),
party_size: z.number().int().min(1).max(20),
date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
});
export type CreateReservationRequest = z.infer;
// テスト(スキーマに基づく)
describe("CreateReservationSchema", () => {
it("有効なリクエストを受け入れる", () => {
const result = CreateReservationSchema.safeParse({
guest_name: "田中",
party_size: 4,
date: "2026-06-01",
});
expect(result.success).toBe(true);
});
it("party_sizeが0ならエラー", () => {
const result = CreateReservationSchema.safeParse({
guest_name: "田中",
party_size: 0, // 仕様: minimum: 1
date: "2026-06-01",
});
expect(result.success).toBe(false);
});
});
## 開発手法: 仕様駆動開発
- 実装の前に仕様(API定義・スキーマ)を書く
- API: OpenAPI YAML または Pydantic/Zod スキーマで入出力を定義
- スキーマからテストケースを生成し、テストが通るように実装する
- 仕様が真実の源。実装と仕様が矛盾したら仕様を正とする