TDD总结

wangmiaoyan 2014-09-04

TDD(测试驱动开发)是敏捷开发中的一项核心实践和技术,也是一种设计方法论。TDD的原理是在开发功能代码之前,先编写单元测试用例代码,测试代码确定需要编写什么产品代码。TDD虽是敏捷方法的核心实践,但不只适用于XP(Extreme Programming),同样可以适用于其他开发方法和过程。

TDD的基本思路就是通过测试来推动整个开发的进行,但测试驱动开发并不只是单纯的测试工作,而是把需求分析,设计,质量控制量化的过程。

TDD的重要目的不仅仅是测试软件,测试工作保证代码质量仅仅是其中一部分,而且是在开发过程中帮助客户和程序员去除模棱两可的需求。TDD首先考虑使用需求(对象、功能、过程、接口等),主要是编写测试用例框架对功能的过程和接口进行设计,而测试框架可以持续进行验证。

————摘自《百度百科》

刚刚接触TDD,感觉就是个坑啊,还没有掌握好之前学习的东西,又硬生生改变的思维去写测试,每一步都反复琢磨,才勉强写完一个测试。

现在测试工具有很多,我这里用的是Jasmine,Jasmine项目主页:https://github.com/pivotal/jasmine

Jasmine的基本的用法:

describe('pos', function () {

}

 describe表示一个测试组。接写来的测试都写在里面:it('should print correct text', function () {

spyOn(console, 'log');

        printInventory(inputs);

        var currentDate = new Date(),
            year = dateDigitToString(currentDate.getFullYear()),
            month = dateDigitToString(currentDate.getMonth() + 1),
            date = dateDigitToString(currentDate.getDate()),
            hour = dateDigitToString(currentDate.getHours()),
            minute = dateDigitToString(currentDate.getMinutes()),
            second = dateDigitToString(currentDate.getSeconds()),
            formattedDateString = year + '年' + month + '月' + date + '日 ' + hour + ':' + minute + ':' + second;

        var expectText =
            '***<没钱赚商店>购物清单***\n' +
            '打印时间:' + formattedDateString + '\n' +
            '----------------------\n' +
            '名称:雪碧,数量:5瓶,单价:3.00(元),小计:12.00(元)\n' +
            '名称:荔枝,数量:2斤,单价:15.00(元),小计:30.00(元)\n' +
            '名称:方便面,数量:3袋,单价:4.50(元),小计:9.00(元)\n' +
            '----------------------\n' +
            '挥泪赠送商品:\n' +
            '名称:雪碧,数量:1瓶\n' +
            '名称:方便面,数量:1袋\n' +
            '----------------------\n' +
            '总计:51.00(元)\n' +
            '节省:7.50(元)\n' +
            '**********************';

        expect(console.log).toHaveBeenCalledWith(expectText);
    });

 其中:

it('should print correct text', function () {

}

 每一个这样的it语句块就是一个单元测试的内容,我们在‘ ’中写下这个单元的名称,一般是写我们想要得到的结果,然后再function里面得到我们想要的内容,在这里,我们用spyon模拟printInventory(inputs)中的console.log()函数,而

expect(console.log).toHaveBeenCalledWith(expectText);

 就是将console.log输出的值与expectText匹配,如果匹配成功,测试才会通过,现在

printInventory(inputs);

 还没有实现,所以肯定会报错的,新手可以在函数中写入:

var currentDate = new Date(),
            year = dateDigitToString(currentDate.getFullYear()),
            month = dateDigitToString(currentDate.getMonth() + 1),
            date = dateDigitToString(currentDate.getDate()),
            hour = dateDigitToString(currentDate.getHours()),
            minute = dateDigitToString(currentDate.getMinutes()),
            second = dateDigitToString(currentDate.getSeconds()),
            formattedDateString = year + '年' + month + '月' + date + '日 ' + hour + ':' + minute + ':' + second;

        var expectText =
            '***<没钱赚商店>购物清单***\n' +
            '打印时间:' + formattedDateString + '\n' +
            '----------------------\n' +
            '名称:雪碧,数量:5瓶,单价:3.00(元),小计:12.00(元)\n' +
            '名称:荔枝,数量:2斤,单价:15.00(元),小计:30.00(元)\n' +
            '名称:方便面,数量:3袋,单价:4.50(元),小计:9.00(元)\n' +
            '----------------------\n' +
            '挥泪赠送商品:\n' +
            '名称:雪碧,数量:1瓶\n' +
            '名称:方便面,数量:1袋\n' +
            '----------------------\n' +
            '总计:51.00(元)\n' +
            '节省:7.50(元)\n' +
            '**********************';

        printInventory = function(inputs) {

            console.log('expectText');
        };

以让测试成功通过,保证测试本身不是错的。

接下来我们可以删掉不必要的代码了,然后真正实现功能。

再多说一点关于测试的东西,前面说到describe表示一个测试组,在describe中可以写无数个it语句块用来测试每一个单元,如果有一个it语句块提示错误,那么就不是哪一个实现模块出错,有可能是实现代码整体就出错了,其他的it语句块碰巧通过了而已,所以当测试报错之后,首先看提示,如果expect的期望值和实际值匹配不一致,可以用倒推的思想,逐步检查到底哪一步出错了,如果是代码本身的问题,可能你就要重写代码了。这样的倒推效率也是比较低的,所以当我们写测试的时候,首先要根据功能确定好测试框架,保证整体的思维不是错的,测试可以小步小步的进行,保证每一个小的实现都有测试与之对应。这样,测试提示错误的时候,我们就很容易找到错误的源头。

相关推荐