前言
如果你關注軟件開發最佳實踐方面的話題,你肯定聽說過測試驅動開發(TDD - Test Driven Development) 和行為驅動開發(BDD - Behavior Driven Development)。這篇文章會為你闡述這兩種模式的含義並舉例,同時對二者進行比較。
測試驅動開發 (TDD)
當我第一次聽到TDD這個詞,從字面上理解,覺得很簡單,就是用於驅動軟件開發的測試。
這沒有錯,如果對TDD作進一步的解釋,這個過程可以進一步分解為5個步驟:
- 首先,開發者在碼業務前寫一些測試用例
- 運行這些測試用例。結果肯定是運行失敗,因為測試用例中的業務邏輯還沒實現嘛
- 開發者實現測試用例中的業務邏輯
- 再運行測試用例, 如果開發者代碼能力不錯,這些測試用例應該可以跑通了(pass)
- 對業務代碼及時重構,包括增加注釋,清理重復等。因為沒人比開發者自己更了解哪些代碼會對哪些部分造成影響從而導致測試失敗(fail)
當需要開發新需求新功能時,重復上述步驟。流程如下圖所示:
TDD舉例
我們通過舉例來了解一下如何實踐TDD。例子中的代碼可以從github上獲取tdd-vs-bdd。將代碼clone下來,執行命令npm install && grunt
假設我們想寫一個計算階乘的函數(這是一個很刻意的例子,但是這個例子對我們指出TDD和BDD的區別很有幫助)。TDD的常用方式是運行某函數,然后斷言結果滿足某個值。
在階乘的例子中,我們使用的javascript測試框架是Mocha。廢話不說,上代碼:
var assert = require('assert'), factorial = require('../index'); suite('Test', function (){ setup(function (){ // Create any objects that we might need }); suite('#factorial()', function (){ test('equals 1 for sets of zero length', function (){ assert.equal(1, factorial(0)); }); test('equals 1 for sets of length one', function (){ assert.equal(1, factorial(1)); }); test('equals 2 for sets of length 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); };
-
現在我們再次運行測試用例,所有的case都跑通了! 這就是TDD的使用方式。
我們接着來學習BDD,看它與TDD有什么不同。
行為驅動開發 (BDD)
BDD是什么? 很多人都會感到很模糊。 有人說它與TDD類似,有人說它是對TDD做了擴展。
拋開晦澀的定義,我們只需要記住一點:BDD旨在消除TDD過程中可能造成的問題。
與TDD相比,BDD是通過編寫行為和規范來驅動軟件開發。 行為和規范可能看起來與測試非常相似,但是它們之間卻有着微妙但重要的區別。
BDD舉例
我們還以講解TDD中用到的階乘函數為例:
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', function (){ factorial(3).should.equal(6); }); }); after(function () { // Anything after the tests have finished }); });
看出TDD和BDD的區別了嗎?其實就是措辭。BDD的描述采用了更加’繁瑣’的描述風格,閱讀BDD的測試用例就像是閱讀一篇文檔。
這正是為什么我說BDD旨在消除TDD過程中可能造成的問題的原因所在。BDD賦予的這種像閱讀句子一樣閱讀測試的能力有助於帶來對測試認知上的轉變,有助於我們去考慮如何更好寫測試。當你可以流暢的閱讀自己寫的測試,你自然可以寫出更好更全面的測試用例。
盡管上面的舉例非常簡單,當我們可以看出:BDD更注重功能本身而非單純的測試用例運行結果。這也是我們經常聽到的一句關於BDD本質的另外一種表達方式:BDD幫助開發人員設計(design)軟件,TDD幫助開發人員測試(test)軟件。
TDD vs BDD
在TDD和BDD之間做選擇不是件容易的事。這取決於開發者使用的語言是否有合適的測試框架,小組的同學們是否適應對應框架的用法等等。
有人總是聲稱BDD優於TDD,因為BDD有助於消除TDD開發中可能產生的問題(issue)。
BDD可能有助於防止問題,但並不能保證消除所有問題。一些由糟糕的代碼結構,不好的編程實踐引發的問題不可能通過BDD就可以消除的。只是如果開發者BDD測試寫的很糟糕,那基本上也不可能開發出健壯的功能。
轉自https://blog.csdn.net/yhc166188/article/details/102881306