贾静测试TDD03
徐昊
你好,我是徐昊。今天我们来继续进行命令行参数解析的 TDD 演示。
首先让我们回顾一下题目与需求与代码进度。如前所述,题目源自 Bob 大叔的 Clean Code 第十四章:
我们中的大多数人都不得不时不时地解析一下命令行参数。如果我们没有一个方便的工具,那么我们就简单地处理一下传入 main 函数的字符串数组。有很多开源工具可以完成这个任务,但它们可能并不能完全满足我们的要求。所以我们再写一个吧。
传递给程序的参数由标志和值组成。标志应该是一个字符,前面有一个减号。每个标志都应该有零个或多个与之相关的值。例如:
-l -p 8080 -d /usr/logs
“l”(日志)没有相关的值,它是一个布尔标志,如果存在则为 true,不存在则为 false。“p”(端口)有一个整数值,“d”(目录)有一个字符串值。标志后面如果存在多个值,则该标志表示一个列表:
-g this is a list -d 1 2 -3 5
"g"表示一个字符串列表[“this”, “is”, “a”, “list”],“d"标志表示一个整数列表[1, 2, -3, 5]。
如果参数中没有指定某个标志,那么解析器应该指定一个默认值。例如,false 代表布尔值,0 代表数字,”"代表字符串,[]代表列表。如果给出的参数与模式不匹配,重要的是给出一个好的错误信息,准确地解释什么是错误的。
确保你的代码是可扩展的,即如何增加新的数值类型是直接和明显的。
目前我们的代码结构如下图所示:
![](https://static001.geekbang.org/resource/image/e6/c4/e6efe45de49576d10b0f8b9505c6b8c4.jpg?wh=7064x3323)
我们目前的任务列表为:
调整任务列表
当我们罗列任务列表的时候,还没有进行重构,系统中也只有 Args 一个类。而经过重构之后,我们提取了 OptionParser 接口,以及与之对应的实现类:BooleanOptionParser 和 SingleValuedOptionParser。那么当再去构造测试的时候,就存在两个不同的选择:继续针对 Args 进行测试,或是直接对 BooleanOptionParser 进行测试。
代码分别如下所示:
在当前的架构下,这两个测试是等效的功能验证,但是它们的测试范围不同,在下图中,我用虚线边框圈定了它们的范围:
![](https://static001.geekbang.org/resource/image/61/a5/614c3b883bdd3c45f59285992ec502a5.jpg?wh=7487x4213)
那么在这种情况下,我们可以选择粒度更小的测试,这样更有益于问题的定位。于是,我们可以修改任务列表,将剩余的任务分配到对应的组件上去:
现在让我们进入红 / 绿循环:
00:00 / 00:00
1.0x
- 2.0x
- 1.5x
- 1.25x
- 1.0x
- 0.75x
- 0.5x
类似的,根据任务列表,完成 SingleValuedOptionParser 的功能:
00:00 / 00:00
1.0x
- 2.0x
- 1.5x
- 1.25x
- 1.0x
- 0.75x
- 0.5x
按照测试策略重组测试
在这个红 / 绿环节中,我们发现在整数类型和字符串类型的异常场景中,差异仅仅在于如何构造 SingleValuedOptionParser:
也就是说,仅仅是测试代码的差别,而被测试的代码则没有任何区别。我们按照任务列表,再构造其他场景的测试,也仅仅是不同测试数据的重复而已。所以将剩余任务从列表中取消就好了。
在当前的代码中,还遗存着一些重构前的测试。对比经过重构之后新写的测试,就会发现对于类似的功能,我们测试的出发点和测试的范围都有不同,这是一种坏味道。我们需要对测试进行重构,以消除这些不一致:
00:00 / 00:00
1.0x
- 2.0x
- 1.5x
- 1.25x
- 1.0x
- 0.75x
- 0.5x
在继续完成其他功能之前,我们可以快速审查一下代码,可以显而易见地发现几个明显的 Bug,那么我们可以通过一系列红 / 绿环节来修复它们:
00:00 / 00:00
1.0x
- 2.0x
- 1.5x
- 1.25x
- 1.0x
- 0.75x
- 0.5x
好了,到此为止,我们得到了一个颇为健壮的代码,以及清晰、可扩展的代码结构。
小结
在这节课中,我们展示了红 / 绿 / 重构循环是如何与任务列表互动,任务列表又是怎样持续指导我们进行测试驱动开发的。让我们回想一下最开始构想的任务列表:
我们真正的开发过程是这样的,先按照任务列表完成了一块功能点:
发现了坏味道,开始重构。通过重构引入了新的组件,改变了架构。于是剩余的任务列表改为:
陆续完成这些任务,发现不一致的测试策略,重组测试。然后进行代码审查,发现了几个缺陷,于是剩余任务列表变为(请重点关注列表的变化):
不难发现,任务列表是一个随代码结构(重构)、测试策略(在哪个范围内测试)、代码实现情况(存在哪些缺陷)等因素而动态调整的列表。它的内容体现了我们最新的认知,它的变化记录了我们认知改变的过程。
下节课,我们将继续完成命令行列表标志的功能。我们会重复任务分解与红 / 绿 / 重构循环。请注意,对于列表标志的任务分解与我们已完成的功能有何不同。
思考题
请根据当前代码结构,对列表标志功能进行任务分解。
欢迎把你学习这节课的体会与思考分析在留言区,也欢迎你把课程分享给自己的同事或朋友,我们下节课再见!
公开
同步至部落
取消
完成
0/2000
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
![](https://static001.geekbang.org/resource/image/d0/e4/d0880927e2a522a038be2d04bf19dfe4.png)
本文介绍了如何使用测试驱动开发(TDD)的方式来进行命令行参数解析的演示。文章首先回顾了需求和代码进度,然后讨论了如何进行任务列表的调整和重构,以及如何根据任务列表进行红/绿循环来完成功能。作者展示了如何根据任务列表完成功能点,发现坏味道后进行重构,并通过红/绿循环来修复缺陷。文章强调了任务列表的重要性,它是动态调整的,记录了认知的改变过程。最后,作者提出了一个思考题,要求读者根据当前代码结构对列表标志功能进行任务分解。整体来说,本文强调了TDD的重要性,以及如何通过任务列表和红/绿循环来指导开发过程,对读者进行了一次技术实践的指导和启发。
2022-03-21给文章提建议
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《徐昊 · TDD 项目实战 70 讲》,新⼈⾸单¥98
《徐昊 · TDD 项目实战 70 讲》,新⼈⾸单¥98
立即购买
![unpreview](https://static001.geekbang.org/resource/image/fc/68/fcedb3d77ed59f0105114c4437a7e068.png)
登录 后留言
精选留言
由作者筛选后的优质留言将会公开显示,欢迎踊跃留言。
收起评论