刚入行那会儿,我写的代码总是在上线后出各种问题。修完一个bug,另一个又冒出来,像打地鼠一样。直到有位老同事甩给我一句话:‘你先写测试,再写代码试试?’ 我一脸懵,但还是照做了。结果发现,代码反而写得更快了,出错也少了。
\n\n什么是测试驱动开发
\n测试驱动开发(TDD)不是先写功能再补测试,而是反过来——先写测试用例,再写实现代码。整个过程就三步:
\n- \n
- 写一个失败的测试 \n
- 写刚好让测试通过的代码 \n
- 优化代码结构,不改变行为 \n
这个循环叫“红-绿-重构”:测试失败是红色,通过是绿色,然后清理代码。
\n\n举个实际例子
\n假设你要做一个打印计费功能,每页收费0.5元。别急着写逻辑,先写测试:
\ndef test_print_cost():\n assert calculate\_print\_cost(1) == 0.5\n assert calculate\_print\_cost(2) == 1.0\n assert calculate\_print\_cost(0) == 0.0\n\n这时候运行测试,肯定会报错,因为 calculate\_print\_cost 根本不存在。接着,你才去创建这个函数,写最简单的实现:
def calculate\_print\_cost(pages):\n return pages * 0.5\n\n再跑测试,通过了。接下来可以加更多场景,比如负数页数、小数页数,看看会不会出问题。
\n\n为什么打印扫描这类系统更需要TDD
\n你在单位负责维护一台共享打印机,经常有人抱怨“明明打了三页,怎么扣了五页的钱?” 问题往往出在计数逻辑分散在多个地方,改一处,另一处就崩。
\n\n用TDD,先把所有计费规则写成测试,哪怕设备没连上,代码没写完,至少你知道“正确的行为”是什么。以后任何人改代码,跑一遍测试就知道有没有搞砸。
\n\n从小处开始练手
\n别一上来就想把整个扫描模块都TDD化。先挑个小功能,比如判断文件是否支持打印(PDF、图片等),写几个测试:
\ndef test_is\_supported\_format():\n assert is\_supported(\"report.pdf\") == True\n assert is\_supported(\"photo.jpg\") == True\n assert is\_supported(\"virus.exe\") == False\n assert is\_supported(\"notes.txt\") == False\n\n然后实现函数,让它通过。就这么简单,每天练一个,三个月后你会觉得写测试比写文档还自然。
\n\n很多人说“项目紧,没时间写测试”,其实写测试花的那点时间,早就在调试和返工里省回来了。就像复印前先预览,看着多此一举,可真印错了,浪费的可是整张纸和墨粉。
","seo_title":"测试驱动开发入门指南 | 实用编程技巧","seo_description":"想写出更稳定的代码?从测试驱动开发(TDD)开始。本文用打印计费等真实场景,带你一步步实践TDD核心流程,适合初学者上手操作。","keywords":"测试驱动开发, TDD入门, 编程实践, 单元测试, 软件开发技巧"}