zoukankan      html  css  js  c++  java
  • 测试驱动开发实践

    总是以为自己了解了测试驱动开发,其实做起来和了解根本不是一回事。原来觉得代码清晰得很,后来试验了一下才知道那是自己的错觉。这次,让我们抛却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和敏捷理解不深,随时会似是而非最终偏离航道的。

    (未完……)

  • 相关阅读:
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    SVN分支
    SVN分支
    SVN 版本回退
    SVN 版本回退
    如何在excel中取消合并单元格后内容自动填充?
    如何在excel中取消合并单元格后内容自动填充?
    如何让自己像打王者荣耀一样发了疯、拼了命的学习?
  • 原文地址:https://www.cnblogs.com/wang-ze/p/5671879.html
Copyright © 2011-2022 走看看