测试驱动开发实践

总是以为自己了解了测试驱动开发,其实做起来和了解根本不是一回事。原来觉得代码清晰得很,后来试验了一下才知道那是自己的错觉。这次,让我们抛却Eclipse的自动补全功能,来一场真正的测试驱动开发吧。

项目描述:这是一个很简单的项目,目标是扫描磁盘上所有特定格式的文件,将其路径存储下来,通过程序可以快捷搜索到文件路径并自动定位到该文件。

用户故事(简单点写了):

1、              扫描磁盘,将目录下的所有文件列出来,将特定格式的文件信息存储到磁盘。

2、              所有文件的信息可以被查询。

3、              被查询出的信息可以双击打开所在文件夹并定位该文件。

好了,这就是第一次的迭代目标,其中文件的格式枚举,存储到磁盘的形式,都可以以后再说,那么针对于故事的过程,我们开始设计并写测试吧:

设计:

1、          平面文件存储,每个文件以行为单位存储,不同属性以###分割,实例化到FileInfo类(故事1)。

2、          平面文件叫fileDB。文件以行读取到List,以带格式的String写入(故事1)。

3、          特定文件格式以正则表达式匹配(故事1)。

4、          查询的条件是文件名,通过遍历List查找属性是否符合contains规则(故事2)。

5、          用JNI explorer打开并定位文件(故事3)。

建立测试:

这里首先关注的是设计中的第一条。

新建一个Junit Test Case,我将测试的类叫FileInfo,所以这个测试类叫FileInfoTest,它与FileInfo在同一包路径下,但是在不同的resource folder下。

这个Test Case应该不能通过测试。

事实证明,它的确无法通过测试

然后,它应该这样被初始化。

编译错误!那当然,因为类FileInfo还不存在,让我们建立它。

编译通过了,我们需要它将字段输出成一个带###分隔符的字符串,字符串的组成是FileName###FileDir###FilePath###LastUpdate。

那么测试应该变成这样了:

为了解决这些红杠,FileInfo得变成这样。

(这里有那么一点点牵强,就是get方法和成员变量的来源不是“刚刚好通过测试”,而是测试原本是为了引出成员变量)

现在toString应该变成这样:a.txt###c:\###c:\a.txt###2016-01-01。

所以测试应该变成这样(这样写代码好费时间!但参与设计的过程也相应变多,思考和工作量都在增长)

当然,测试失败了,二者并不相等

 

原因当然在toString

修改FileInfo的toString方法:

测试通过了!

此时,我在想,如果因为某种原因,我想将###换成@@@,那么toString方法中###应该以变量的形式出现。但因为此次将修改的代码对通过测试没有任何意义,也不能增加功能,所以我不这么做。我会在什么时候这样做呢?我会等到代码的功能很多,我重构它并能展示此时测试对我重构的意义的时候。

现在我们完成了设计1,来开始设计2吧。

将fileDB.txt建立在项目根路径下,为了便于之后的测试,写入如下内容:fileName###fileDir###filePath###lastUpdate。

然后新建一个测试类,用于测试还没有建立的类是否能读取fileDB并且按行存储到List。

那么测试类应该是这个样子:

让它通过编译。必要时,甚至可以遵从Eclipse建议的做法。

执行测试,报错。

List.get(0)的问题,list是空的,那么,让我们放点东西进去。

这算什么!这不就是骗人的吗?但是我刚好通过了测试的问题,现在进入测试的下一个问题。

 

现在是将fileDB.txt读取,并放入数据的时候了。但此时我们好像需要额外的几个方法。

好像闻到了代码的异味,但是测试通过了。很可惜,我不知道这种情况应该怎么处理,所以我决定改变测试以来改变代码!

好了,让我们再次恰恰好通过测试吧。另外,我们可能还需要readFileToList和getFileList的测试。刚刚我们好像忘记了,如果测试类调用了某个实例的方法,我们应该首先对实例的方法进行测试编码。

怎么办怎么办?我没法解释这个私有方法的由来,这是我重构本能决定的,和测试没有任何关系。这里应该是我对TDD理解不深的地方。

测试通过了。我能料到以后如果getFileInfoByLine的规则变化的话,这个私有方法还没有被测试覆盖,是一个隐患,但是现在该怎么办呢?因为它是私有的,甚至无法被其他类调用。

好吧,既然它是私有的,那么暂时就只保证所有调用它的方法测试通过吧。

就此,我们完成了第二个设计。这时候我发现一个严重的问题,就是我的设计没有覆盖用户故事中的对磁盘的扫描。

目前为止,这个不严谨的实践也告诉我们,如果对TDD和敏捷理解不深,随时会似是而非最终偏离航道的。

(未完……)

原文地址:https://www.cnblogs.com/wang-ze/p/5671879.html