hello-sdd:从零掌握规格驱动开发的Python实战课程
> 一个从零开始教授规格驱动开发(SDD)的Python实战课程,用完整项目带你打通需求到代码的自动化链路。
## 为什么需要SDD?——先聊聊传统开发的痛点
如果你写过几年代码,大概率经历过这样的场景:
- **需求文档与代码脱节**:产品经理写了一份100页的PRD,开发看完后凭感觉写代码,测试凭经验造数据,三个月后没人说得清某个字段为什么这么命名。
- **测试覆盖靠运气**:手动写单元测试,总是漏掉边界条件,等到线上出bug才发现某个分支根本没测过。
- **API变更引发连锁崩溃**:后端改了个响应字段名,前端没同步,联调时炸出一堆问题,最后靠人肉沟通弥补。
- **代码评审变成‘猜谜游戏’**:reviewer看不懂业务逻辑,只能看语法风格,真正的业务漏洞被掩盖在代码噪音里。
**Spec-Driven Development(规格驱动开发)** 的核心思想是:让**可执行的规格(spec)** 成为开发流程的中心——规格既是需求文档,又是测试用例,还是API契约的单一事实来源。它把“人读文档”变成“机器读spec”,让需求、代码、测试三者从出生就绑定在一起。
## hello-sdd 是什么?
这是由西班牙知名开发者 **Brais Moure**(mouredev)发起的免费开源课程,用 **Python** 从零讲解SDD的完整实践。项目仓库本身就是一个活教材——每个commit都对应课程的一个阶段,你可以跟着git历史一步步看到项目如何从空目录演进到带完整测试和文档的SDD样板。
项目地址:https://github.com/mouredev/hello-sdd
## 安装与快速上手
### 环境要求
- Python 3.10+(推荐3.12)
- pip
- 建议使用虚拟环境
### 安装步骤
bash
# 克隆仓库
git clone https://github.com/mouredev/hello-sdd.git
cd hello-sdd
# 创建虚拟环境(可选但推荐)
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# 安装依赖
pip install -r requirements.txt
# 运行测试(验证环境正常)
pytest
### 最小示例:从spec到测试
课程的核心工作流是:**先写spec(用YAML或Python描述),再自动生成测试骨架,最后实现代码让测试通过**。
项目里有一个典型的例子——`calculator`模块。首先,你定义规格文件`specs/calculator_spec.yaml`:
yaml
Calculator:
add:
description: 两个数相加
params:
a: {type: number, required: true}
b: {type: number, required: true}
returns: {type: number}
examples:
- {a: 2, b: 3, expected: 5}
- {a: -1, b: 1, expected: 0}
- {a: 0, b: 0, expected: 0}
divide:
description: 除法,除数为零时抛异常
params:
a: {type: number, required: true}
b: {type: number, required: true}
returns: {type: number}
exceptions:
- ZeroDivisionError
examples:
- {a: 10, b: 2, expected: 5}
- {a: 5, b: 0, raises: ZeroDivisionError}
然后,课程教你用`pytest`的`pytest-subtests`或自定义的`spec_runner`,把这份YAML直接变成测试:
python
# tests/test_calculator_from_spec.py
import pytest
import yaml
from pathlib import Path
from calculator import Calculator
@pytest.mark.parametrize("spec_file", ["specs/calculator_spec.yaml"])
def test_calculator_spec(spec_file):
spec = yaml.safe_load(Path(spec_file).read_text())
calc = Calculator()
for method_name, behavior in spec["Calculator"].items():
for example in behavior.get("examples", []):
if "raises" in example:
with pytest.raises(getattr(__builtins__, example["raises"])):
getattr(calc, method_name)(example["a"], example["b"])
else:
result = getattr(calc, method_name)(example["a"], example["b"])
assert result == example["expected"], f"{method_name}{example} failed"
当你运行`pytest`时,测试会失败(因为`calculator.py`还没实现)。然后你根据spec写实现:
python
# calculator.py
class Calculator:
def add(self, a, b):
return a + b
def divide(self, a, b):
return a / b # 自然抛ZeroDivisionError
再运行`pytest`,全绿。这就是SDD的“红-绿-重构”循环,只不过这里的“红”不是因为测试拍脑袋写的,而是因为规格本身定义了行为。
## 核心亮点深度解析
### 1. 规格即契约(Spec-as-Contract)
课程强调,spec不是“文档”,而是**机器可读的契约**。它同时服务于:
- **开发者**:明确知道每个函数的输入输出约束
- **测试**:直接生成测试用例,无需重复编写
- **API消费者**:如果对外提供REST API,spec可以转化为OpenAPI schema
项目里专门有一章教你如何用`pydantic`验证spec中的类型,让类型错误在测试前就被捕获。
### 2. 从spec自动生成文档
课程展示了如何用`mkdocs` + `lazydocs`,从spec和docstring生成漂亮的API文档。这样文档永远不会过时——因为spec变了,文档生成器就会产出新版本,而CI可以强制检查spec与代码是否同步。
### 3. 完整的CI/CD集成
项目自带GitHub Actions工作流,在每次push时自动运行:
- `pytest`(从spec生成的测试)
- `mypy`(类型检查)
- `ruff`(lint)
- `mkdocs build`(确保文档可构建)
这意味着**spec是唯一的真源**,所有其他产物(测试、文档、类型检查)都是它的投影。
### 4. 实战项目:任务管理API
课程不只是讲概念,而是带着你构建一个完整的`Todo API`(使用FastAPI)。你从写`specs/todo_api.yaml`开始,定义每个端点的请求/响应/错误码,然后自动生成:
- FastAPI路由的测试
- OpenAPI schema
- 前端可用的TypeScript类型(通过`openapi-typescript`)
整个过程让你直观感受到SDD在真实项目中的威力。
## 适用场景
- **微服务团队**:多个服务间接口频繁变动,用spec统一契约可减少联调痛苦。
- **测试驱动开发(TDD)实践者**:TDD容易陷入“测试先行但需求模糊”的困境,SDD补上了“需求可执行”这一环。
- **开源项目维护者**:用spec让贡献者清楚“什么行为是被期望的”,减少无效PR。
- **教学场景**:课程节奏清晰,每章有练习,适合作为大学软件工程课程的补充教材。
## 同类项目对比
| 项目 | 语言 | 核心理念 | 与hello-sdd的差异 |
|------|------|----------|-------------------|
| **Spec-driven development (SDD) by SpecFlow** | C#/.NET | 使用Gherkin语言(Given-When-Then)描述行为 | 更偏向BDD(行为驱动),需要专门工具链支持;hello-sdd更轻量,纯Python+YAML |
| **OpenAPI + Swagger** | 任何 | 以OpenAPI spec为中心生成代码和文档 | 主要针对REST API,不覆盖纯函数/类级别的规格;hello-sdd同时覆盖函数级和API级 |
| **Hypothesis (Python)** | Python | 基于属性的测试,自动生成极端输入 | 不涉及需求文档或契约,只解决测试数据生成问题;hello-sdd更关注开发流程规范 |
| **Cucumber** | 多语言 | BDD框架,用自然语言写场景 | 需要额外维护“步骤定义”代码,与业务代码耦合;hello-sdd的spec直接映射到函数签名,更简单直接 |
**hello-sdd的独特优势**:
- **零外部依赖**:只需要Python标准库 + pytest + yaml,不像SpecFlow那样需要Visual Studio插件。
- **渐进式采用**:你不需要一开始就全面SDD,可以从一个模块开始,课程也教了如何逐步迁移。
- **教学导向**:Brais Moure是知名教育者,课程每章视频+代码+练习,社区活跃(GitHub Discussions)。
## 局限与思考
- **Python生态限制**:课程完全基于Python,如果团队是Java/Go,需要自行移植概念。
- **规格膨胀风险**:如果项目极大,spec文件本身也会变得复杂,需要维护spec的spec(元规格)。
- **文化阻力**:SDD要求团队改变“先写代码再补文档”的习惯,初期有学习成本。
## 总结
hello-sdd不是又一个“测试框架”,而是一套**开发方法论**的完整落地。它最宝贵的不是代码,而是课程里反复强调的三个原则:
1. **先定义行为,再写实现** —— 让“做什么”先于“怎么做”。
2. **规格可执行** —— 让文档不再说谎。
3. **自动化一切** —— 从测试到文档到CI,全部由spec驱动。
如果你厌倦了“需求-代码-测试”三方扯皮,或者想给自己的项目建立更可靠的契约体系,这个仓库值得你花一个周末仔细跟一遍。Brais Moure的课程质量在西班牙语开发者社区有口皆碑,而这份英文代码库+中文解读,恰好能让你跨过语言门槛,直接吸收SDD的精髓。
**项目地址**:https://github.com/mouredev/hello-sdd