TDD vs. BDD

如果你一直在关注最新的软件开发,你一定听过测试驱动开发(Test-driven development TDD)和行为驱动开发(Behavior-driven development BDD)。这篇文章说明比较了这两种不同的开发模式,并提供了例子。

 

Test Drive Development,测试驱动开发

当我第一次听说TDD,就觉得它是一个很简单的概念,TDD是使用测试案例等来驱动你的软件开发。

 

如果我们想要更深入点了解TDD,我们可以将它分成五个不同的阶段:

1.首先,开发人员编写一些测试方法。

2.其次,开发人员使用这些测试,但是很明显的,测试都没有通过,原因是还没有编写这些功能的代码来实际执行。

3.接下来,开发人员实现测试中的代码。

4.如果开发人员写代码很优秀,那么在下一阶段会看到他的测试通过。

5.然后开发人员可以重构自己的代码,添加注释,使其变得整洁,开发人员知道,如果新添加的代码破坏了什么,那么测试会提醒他失败。

 

这种周期不断的循环下去,只要开发者有更多的功能需要开发。流程图如下:

Test-driven development flowchart

 

例子:

我们来看看一个开发人员是怎么来做着几个步骤的。这篇文章的完整的代码在:https://github.com/jdavis/tdd-vs-bdd,代码免费下载,你可以使用以下命令来运行:npm install && grunt

 

比方说,开发人员希望写一个简单的函数来极端阶乘(这个例子很简单,但它会告诉我们TDDBDD之间的差异)。TDD的常规做法是使用这个方法(function),然后断言(assert)计算结果符合条件。

 

在这个例子中,我们将使用Javascript的测试框架中的Mocha。测试应该和下面这个差不多:

var assert = require('assert'),

    factorial = require('../index');

 

suit('Test', function(){

    setup(function(){

        //Create any objects that we might need

    });

    suit('#factorial()', function(){

        test('equals 1 for sets of zero length', function(){

            assert.equal(1, factorial(0));

        });

        test('equals 1 for sets of lengrh one', function(){

            assert.equal(1, factorial(1));

        });

        test('equals 2 for sets of lengrh two', function(){

            assert.equal(2, factorial(2));

        });

        test('equals 6 for sets of length three', function(){

            assert.equal(6, factorial(3));

        });

    });

});

很明显,测试会失败,因为我们还没有写函数。然后让我们来写满足测试条件的函数。这些函数可能像下面这样:

module.exports = function(n) {

    if(n<0) return NaN;

    if(n===0) return 1;

 

    return n*(factorial(n-1));

}

现在我们运行这个测试,就可以通过了。下面我们看看BDD是怎样工作的。

 

Behavior-Driven Development ,行为驱动开发

好啦,现在你可能要问什么是BDD呢?这个定义呢,就有一点模糊了。有些人会说,它和TDD很像;还有人会说,这就是有着更好的指导的TDD

 

不管它实际的定义是什么,这没有那么重要。最主要的是你要知道BDD可以消除TDD可能存在的问题。

 

TDD比起来,BDD是需要我们先写行为规范(功能明细),在进行软件开发。功能明细和测试看起来非常相似,但是功能明细更加含蓄一些。

 

例子:

让我们继续看一下上面那个例子用BDD如何实现:

var assert=require('assert'),

    factorial = require('../index');

 

describe('Test', function(){

    before(function(){

        //Stuff to do before the tests, like imports, what not

    });

 

    describe('#factorial()', function(){

        it('should return 1 when given 0', function(){

            factorial(0).should.equal(1);

        });

        it('should return 1 when given 1', function(){

            factorial(1).should.equal(1);

        });

        it('should return 2 when given 2', function(){

            factorial(2).should.equal(2);

        });

        it('should return 6 when given 3', funcrion(){

            factorial(3).should.equal(6);

        });

    });

 

    after(function(){

        //Anything after the tests have finished

    });

});

最主要的区别在于描述的不同。BDD采用了更详细的方式使得它看起来就像是一句话。

 

这就是我所说的BDD可以解决一些TDD可能导致的问题。让你的测试看起来更像一个句子,是一种认知上的转变,你会更多的去考虑如何写你的测试。有一种说法是,如果你可以毫无障碍的阅读你的测试,你自然会写出更好的、更全面的测试。

 

这个例子很简单,我们不需要对其做过多的说明。BDD测试应该注重功能而不是实际的结果。你常常会听说BDD是帮助设计软件,而不是像TDD那样的测试软件。

 

TDD VS BDD

TDDBDD之间做选择是比较复杂的事情。这取决于你使用的语言是否有一个合适的测试框架,你的同事们是否熟悉他等等因素。

 

有些人认为BDD总比TDD要好。因为它能够消除TDD带来的问题。

 

BDD的关键在于,他并不是总能够保证阻止问题的发生。就像那些糟糕的代码组织或者是糟糕的设计的问题依然存在。使用测试让你写糟糕代码的可能性降低,从而有更强大的功能。

 

结论

哪一种测试方案会更好,这完全取决于个人。一个知道如何写优秀的TDD测试的人可能和另一个写优秀的BDD测试的人所写出代码的bug一样少。如果你发现你自己使用TDD写了不完整的测试,并希望设计更好的软件,那么不妨使用下BDD。如果你是一个学习TDDBDD的新手,我建议你先学习TDD。这两种风格最重要的部分就是强制你写你代码的测试样例。如果你从不测试你的代码,你会需要他们的。

 

我不是一个研究TDDBDD的专家。我只是知道他们之间的一点区别,并研究了以下。再次说明,文中的代码位于:https://github.com/jdavis/tdd-vs-bdd。

 

如果您对这篇文章有建议或错误改正。或者只是提出你的不同意的观点,我很乐意听到这一切。请随时与我联系。感谢您的阅读!

 

原文链接:

https://joshldavis.com/2013/05/27/difference-between-tdd-and-bdd/

posted @ 2014-10-27 16:14 花田里的猪猪 阅读(...) 评论(...) 编辑 收藏