行为驱动开发BDD概要
BDD脫胎于TDD
行為驅動開發(Behavior-Driven Development,簡稱BDD),是在測試驅動開發(Test-Driven Development,TDD)基礎上發展而來的一種軟件開發方法。TDD最大的弊端,是面對一大堆的功能需求和用例時,往往會感到無從下手。另一方面,由于TDD更側重于測試本身,因此容易忽視對業務需求的表達,最終沉溺于瑣碎細節而無法自拔。
BDD避免了信息丟失
與傳統的軟件開發方法相比,BDD的本質在于盡可能避免在需求描述、用例撰寫、代碼實現、測試等各環節銜接、轉譯過程中發生的信息丟失。為此,BDD以用例Use Case和示例Example為核心,借助Gherkin等一些特有概念和一系列BDD特有工具,以更貼近業務場景的方式,實現軟件需求的完整實現。二者的比較如下圖所示。
傳統軟件開發
BDD開發
?
BDD流程
BDD的每個迭代可以表述為:
- 規劃整個系統,得到抽象的業務目標Business Goal
- 將業務目標細化為若干個具體的功能需求Feature
- 采取Given-When-Then三段式編寫Gherkin,用具體的場景示例Example描述和演示特定的功能
- 將Example轉換為可執行的Specification
- 將Specification再拆解為更低層次的、逼近代碼實現的Low-Level Specification與測試Test
- 從Low-Level Specification中得到代碼實現,并析取活動文檔Living Documentation
?
發掘Business Goal與Feature
采用Why-Who-How-What四步法發掘Business Goal
- Why:出于何種原因要開發此系統?
- Who:誰將從系統中受益?誰是系統的用戶?誰會影響系統的開發?
- How:怎樣才能更便捷、更容易地達成業務目標?
- What:系統能做哪些工作來實現業務目標?
而在從Business Goal發現Feature時,則采用了Why-Who-What-How四步法進行Feature的粒度細分,得到最終的用戶故事。
其中,Capability是“用戶需要能做什么”,而Feature是“軟件能提供怎樣的幫助”
?
BDD工具
在.NET平臺,從Example到可執行的Specification,有SpecFlow可用;再到Low-Level Specification,有NUnit、RSpec等工具可用。
?
.NET平臺下的BDD開發
在Visual Studio集成環境下,可以按以下步驟實施BDD。
準備工作
為Visual Studio安裝SpecFlow擴展插件
安裝擴展后,將可以在項目中添加用于編寫Gherkin的Feature文件
為項目添加SpecFlow支持包
SpecFlow.NUnit集成了SpecFlow與NUnit,更方便我們編寫相關的測試,所以選擇安裝它即可。如果要使用最新版本的SpecFlow與NUnit,則請分別選擇安裝(NUnit3.0與SpecFlow1.9.0貌似有沖突,測試無法被識別)。如果你喜歡其他的單元測試框架,請選擇并安裝相應類型的package。
撰寫Gherkin
Gherkin,是BDD中采取特定格式、用于描述特定的Feature、形式為特定業務場景示例Example的文本。它較之需求規范Specification更具體明了,有點類似Use Case,但更具體生動,且既可用作測試腳本,又可作為歸檔的內容。
添加Gherkin
為項目添加新項,選擇“SpecFlow Feature File”
編輯Gherkin
打開Feature文件,修改模板內容,得到具體業務需求的描述。其中Feature是功能描述(描述用的文本將自動作為SpecFlow測試的類名),Scenario是具體的業務場景(描述用的文本將自動作為SpecFlow測試名),接著是Given-When-Then的三段式Example描述(描述用的文本將自動作為SpecFlow生成的分步Step的方法名)。
生成可執行的Specification
可執行的Specification,是用來確認業務需求規范是否已被正確實現的自動化測試方法。
每一組Specification,對應Gherkin里的一個Given-When-Then的三段式場景Scenario。三段式的每一個分句,都將對應一個具體的測試方法,這被叫作分步Step。每個Step的方法骨架可借由SpecFlow等BDD工具自動生成,之后再手工修改即可。
SpecFlow+NUnit的組合,可以很容易地編寫出可測試的Step,在Gherkin文本里的Given-When-Then等關鍵字上點擊右鍵,選擇“Generate Step Definitions”即可。在Attribute里出現的(.*)是占位符,類似正則析取參數。
在Build項目后,我們打開單元測試窗口,即可發現SpecFlow測試的蹤影。由于此時每個分步Step里并沒有我們實際的代碼,因此我們運行測試時,會提示Step尚未被實現。
?
為了讓SpecFlow的測試真正動起來,還需要修改Step的實現。簡單演示如下:
新增Account類
namespace BDDExercise{
public class Account
{
public decimal Balance { get; set; }
public void Withdraw(decimal amount)
{
if (Balance - amount >= 0)
Balance -= amount;
}
public void Deposit(decimal amount)
{
if (amount > 0)
Balance += amount;
}
public Account(decimal amount)
{
if (amount > 0)
Balance = amount;
}
}
}
修改Step方法
using NUnit.Framework;using TechTalk.SpecFlow;
namespace BDDExercise
{
[Binding]
public class TransferringMoneyBetweenAccountsSteps
{
private Account _currentAccount;
private Account _savingAccount;
[Given(@"my Current account has a balance of (.*)")]
public void GivenMyCurrentAccountHasABalanceOf(decimal p0)
{
_currentAccount = new Account(p0);
}
[Given(@"my Savings account has a balance of (.*)")]
public void GivenMySavingsAccountHasABalanceOf(decimal p0)
{
_savingAccount = new Account(p0);
}
[When(@"I transfer (.*) from my Current account to my Savings account")]
public void WhenITransferFromMyCurrentAccountToMySavingsAccount(decimal p0)
{
_currentAccount.Withdraw(p0);
_savingAccount.Deposit(p0);
}
[Then(@"I should have (.*) in my Current account")]
public void ThenIShouldHaveInMyCurrentAccount(decimal p0)
{
Assert.AreEqual(_currentAccount.Balance, p0);
}
[Then(@"I should have (.*) in my Savings account")]
public void ThenIShouldHaveInMySavingsAccount(decimal p0)
{
Assert.AreEqual(_savingAccount.Balance, p0);
}
}
}
運行測試
編寫Low-Level Specification
如果說此前可執行的Specification還是一個Scenario的簡單映射,那么這里的Low-Level Specification則可以理解為TDD里的單元測試了。這一步的工作,就是仁者見仁、智者見智了,需要根據具體的業務規則去逐個編寫,并保證足夠的覆蓋率,以驅動整個功能的逐步實現。
Low-Level Specification與之前Specification分割得到的Then分句相比,Then里放簡單的斷言,再用Low-Level Specification更細粒度的單元測試來彌補Then的不足。
生成Living Documentation
歸檔主要還是依賴自動化的工具,比如VS自帶的測試報告或者SpecLog之類更專業的工具等等。
轉載于:https://www.cnblogs.com/Abbey/p/4999634.html
總結
以上是生活随笔為你收集整理的行为驱动开发BDD概要的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Levenshtein Distance
- 下一篇: LocalDB 静默安装