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
查看工具