本文根據中生代技術群分享整理而成,具有多年軟體研發經曆的劉朋為大家分享atdd,tdd,bdd的那些事,為大家分享“以終為始的軟體開發”經驗。
<b>文章正文</b>
我分享的主題是tdd,但是其實涵蓋的領域會更寬泛。于君澤在前幾期裡面分享了“以終為始的架構設計”,其實我的tdd分享并不會僅僅拘泥于tdd,或者說我更想和大家讨論一下“以終為始的軟體開發”,這個題目也許更為恰當。
是以,我其實想讨論的是:作為軟體開發研發團隊,當我們從客戶(或者客戶代表product owner)那裡獲得了對軟體産品的需求,到研發團隊給客戶傳遞了滿足預期的産品,這中間,怎麼才是一個有效的,高效的流程和方法。這是我感興趣的話題,也是我作為研發經理在日常工作中一直在思考和探索的問題。
為了回答這個問題,我們這次先把目光聚焦,我們先來看看三個靈活社群軟體開發人員都會耳熟能詳的模式——atdd,tdd和bdd——能怎樣貢獻到“以終為始的軟體開發”這個目标。
是以,這次分享的第一部分,我們就談談:
要談這個話題,我們首先得了解這三個dd是什麼。在wiki上,對三者的定義是:
atdd
acceptance test-driven development (atdd) is a development methodology
based on communication between the business customers, the developers,
and the testers.
tdd
test-driven development (tdd) is a software development process that
relies on the repetition of a very short development cycle: first the
developer writes an (initially failing) automated test case that defines
a desired improvement or new function, then produces the minimum
amount of code to pass that test, and finally refactors the new code to
acceptable standards.
bdd
in software engineering, behavior-driven development (bdd) is a
software development process that emerged from test-driven development
(tdd).
其實看了這三個wiki上的定義,我隻想說:“然并卵”。說得很玄乎,但是到底什麼是atdd,什麼是tdd,什麼是bdd,它們的關系和聯系是怎樣的呢?它們如何協同應用貢獻到“以終為始的軟體開發”呢?
為了解答這個問題,我們給大家整理了一個30秒弄懂atdd的定義:

如果翻譯成中文,那就是:
<b>【30秒搞懂atdd】</b>
atdd (驗收測試驅動開發)就是一種讓整個研發團隊(po,dev,tester)一起協同讨論和澄清驗收标準(包含執行個體);并基于此提煉出一系列具體的驗收測試(at),然後再開展具體的軟體開發和編碼的實踐。
atdd背後的邏輯:最好的驗證一個研發團隊是否對客戶需求有統一的了解的方法就是對客戶如何驗收有統一的了解。具體到開發工作中,就是有對dod有共同的了解。
有人說,嗯,懂了一些了,但是還是不完全懂~沒有關系,咱們上圖:
圖1 atdd 4d循環
哎呦,這個圖不簡單了,一下子就把atdd,tdd和bdd的關系和聯系展示出來了。如果我們把這個atdd cycle放在scrum實踐中,這個圖長這個樣:
圖2 atdd cycle in scrum
下面,讓我們按照atdd 4d的循環,一個d一個d的來解釋一下。
atdd循環之discuss
目标
充分的了解客戶需求和客戶價值
充分利用團隊成員的不同知識和技能了解需求的不同方面
讓所有團隊成員都獲得對需求的一緻了解
希望解決的問題
對客戶價值了解不正确,後期驗收不通過
開發和測試人員對需求了解不一緻
輸入
從使用者或者使用者代表(po)來的使用者需求(用業務領域的語言描述)
輸出
端到端的使用者故事(end-to-end user story)
采用的實踐
六頂思考帽
一點點解釋:這第一個d(discuss),目标就是讓所有接下來會參與到軟體開發中去滿足客戶需求的各方利益相關者(stakeholder),都能夠在一開始就對使用者想要什麼有統一的了解。是以,這個讨論需要客戶(或者客戶代表),架構師,開發工程師,測試工程師,系統測試工程師,系統內建人員,等等相關各方都能派代表參加。在初期達成的一緻将會大大減少後期的扯皮。這在我們nokia的實踐中已經被證明是能夠很大程度的減少軟體開發中不必要的浪費——代碼完成後的需求扯皮。
另一方面,為了達到這個目的,需要有讨論,讨論就要開會。那怎麼開這個會,也是非常有講究。在我們的實踐中,我們經過嘗試了不同的方法,最終覺得使用“六頂思考帽”的方式是非常有效的方式。(關于什麼是”六頂思考帽“,請自行google之,這裡不再贅述)。
在具體的實踐中,一個需求讨論和澄清的會議的流程這樣的:
藍色帽子——會議主持人
【第一步·白色帽子】收集關于這個需求的<b>背景,事實和資料</b>,供進一步的讨論。注意,這裡不讨論任何怎麼做
【第二步·紅色帽子】在收集完事實之後,是以參會人員的感受如何,是否覺得已經有重複的事實可以進入下一步的需求澄清讨論
【第三步·綠色帽子】讨論正常場景下,客戶需要的是什麼。舉個例子,如果需求是一個使用者名/密碼登入界面,那麼正常情況下軟體需要呈現的功能是什麼。
【第四步·黑色帽子】讨論異常場景下,客戶的需求意味着什麼。繼續上面的例子,在異情況下,比如雙十一超大通路壓力下或者遭受黑客攻擊時,登陸子產品需要呈現的功能是什麼。
【第五步·黃色帽子】決定以上綠色帽子和黑色帽子讨論結果的價值和優先級排序。那在上面的使用者名/密碼登陸子產品例子中,如果對于有限的研發資源和傳遞時間壓力,團隊是先專注哪些功能,是正常情況,還是異常場景處理。
【第六步·紅色帽子】最後,再詢問大家的感受如何,今天的會議是否達到了目的,所有stakeholder都對使用者需求是什麼達成了一緻。
好,說道這裡,大家可能要問:那我們如何表達對用于需求的了解呢?如何确認所有人都有了一緻的了解呢?那就到了atdd循環中第二個d(distill,提煉)。
atdd循環之distill
根據團隊對需求的充分讨論,提煉出需求(feature)的驗收标準以及相應的測試點
驗收标準将成為後續驗收測試用例和産品代碼開發的出發點
驗收标準不清晰,不一緻,導緻後期無法驗收并産出使用者價值
避免出現傳統測試中的“bug海嘯”
端到端的使用者故事(end-to-enduser story)
利用bdd方式描述的驗收标準(acceptancecriteria)
bdd的“given,when,then”行為描述語言
說道這裡,就不得不說一說bdd。bdd的提出者dan,是這麼描述bdd的:
"bddis a 2nd generation, outside-in, pull-based, multiple- stakeholder,multiple-scale, high-automation, agile methodology."
<b>“bdd是第二代由外至内的、基于拉動的、多利益相關者的、多尺度的、高度自動化的靈活方法。”</b>
但是,dan自己也承認,他都不知道這段話說了什麼j然而,我們不得不說,bdd的一個關鍵,看似微小,的改變就是在描述測試點的時候,用“should”替代了“test”。也就是說,<b>你可能會聽到在讨論驗收标準的時候,問題是“預期的行為是什麼?”</b>,而不是“我應該測什麼?”舉個例子,下面圖中女po和身邊的兩位研發團隊骨幹關于“首單打折”這個使用者需求
的讨論完全不在一個頻道上,從業務語言,到僞代碼,到實際的測試函數。無論用哪一種作為描述驗收标準的方式,都無法使所有stakeholder都能了解,并且達成一緻。
是以,如果換成bdd三段論given-when-then模式,将會是下圖這樣。可以看到,現在所有人都能夠用同樣的語言,并且是基于軟體應該有怎樣預期的外部可觀察行為的角度,來統一驗收标準。而given-when-then也天然可以非常容易的在接下來的步驟中轉化為測試用例和指導代碼開發。
好,到這裡,我們已經有了用bdd的三段論(given-when-then)描述的驗收标準,而且所有的stakeholder都有了統一的認識。接下來,我們就可以開始軟體設計和編碼,以及測試了。那就到了:
這一步就很簡單,研發團隊可以使用諸如tdd的模式進行代碼開發;同時,測試團隊根據驗收标準開始準備驗收測試(可以是自動化,也可以是手動)。
當代碼編寫和測試完成之後,那就進入了最後一個環節:示範和驗收。
<b>atdd循環之demo</b>
根據scrum團隊實作同意的definitionof done (dod)對本sprint産出的軟體進行驗收
團隊對驗收标準不清楚
團隊對驗收标準有不同的了解而産生争執
産出的代碼雖然工作,但是沒有創造客戶價值
經過了測試的軟體
通過了驗收标準的可工作和可以釋出給客戶的軟體
acceptance test case作為驗收重要名額
設定對于ut覆寫率,測試自動化率的硬性名額
在這一步中,如果一開始所有的stakeholder都對驗收标準達成了一緻,那這裡的驗收就變得非常簡單:就是把驗收标準拿出來,驗證其中每一個given-when-then是否都有相應的測試用例覆寫;如果需要,po還可以挑選若幹關鍵驗收标準進行現場示範和驗收。
好,說道這裡,我們再把atdd cycle拿出來,大家現在是不是可以總整體上了解atdd,tdd和bdd這三者之間的關系和聯系。以及它們三者如何有機結合,來完成“以終為始的軟體開發”這個目的了呢?
那我們第一次分享就到這裡,我們下次來聊一聊:tdd三原則,同時,我們也來嘗試着回答這個非常挑戰的問題:tdd死了嗎?
q: 你們有沒有核心人員,或多人流動,導緻需要重新和新來人員統一産品定義和驗收标準的情況?是如何處理的。
劉朋: 關于人員流動導緻需要重新定義産品驗收标準的問題,我們之前沒有用bdd來描述test point之前,也很麻煩,就是需要有transfer的成本,但是現在我們的grooming輸出的都是标準格式,用客戶(po)可以看懂的語言描述的驗收标準,其實這個成本就小很多了,因為這些test point(驗收标準)都是很易懂的
因為如果不“幹活”的po都可以懂起,那就不需要transfer成本了噻,哈哈
q:如何提高和改善tdd的開發效率,尤其是在項目開發過程中。我有專門為公司的ui開發架構寫過自動化測試,測試開發實際花費的精力和時間是很多的,如何提高這種開發效率呢?
劉朋:回答問題一如何提高和改善tdd的開發效率:其實kent beck說的tdd不是銀彈,是以并不是所有場合都需要tdd或者适合tdd,比如ui,就不适合用tdd的方式開發;但是如果你說web ui的test automation,那就是acceptance test的問題,是atdd的問題了,那就有很多工具,比如selinimu等等工具來提升自動化測試的效率
q: 驗收測試po要參加吧?還是隻參加demo部分?
劉朋: 驗收測試,在sprint review上area product owner會作為po的代表(如果po不能參加的話),去驗收所有的acceptance test是否都pass
q: 這種以始為終的思想,在推動開發人員思維習慣轉變過程中,能否可以分享一些經驗和關鍵點嗎?
劉朋: 關于“以終為始”觀點的改變,其實atdd是促使大家觀念轉變的第一件事情,第二件事情是“逼迫”大家(至少初期是這樣),用bdd的方式去描述系統應該怎麼工作,應該怎麼驗收,而不是應該怎麼測試;第三件事,是讓大家體會tdd的好處,因為tdd其實也是在潛移默化的讓大家以終為始的思考
其實tdd不是銀彈,但是tdd的思想“以終為始”是銀彈
因為一開始代碼或者設計得可測試性就很低——因為沒有“以終為始”
是以多管齊下,讓大家看到這麼做的好處:和po溝通更順暢了,開發和測試終于有共同的語言來描述驗收标準了;代碼終于不用後補ut了,可測性提高了,都會鼓勵大家繼續用“以終為始”的方式思考
劉朋:嗯,其實kent beck自己也說,即使tdd有一天死了,但是tdd帶來的思維的變化-”以終為始“的思考方式,絕對不會過時:)是以這就是為什麼要把atdd,tdd,bdd放在一起,放在一個整體的圖景中去了解的原因。
江湖:以終為始 我喜歡,做設計 做架構何嘗不是如此
劉朋:這就了解了君澤的架構也是“以終為始”,都是相通的~
其實我特别同意并不是所有team都需要tdd,或者所有項目都需要tdd,kent beck自己也說了farewell tdd,但是他也說了tdd may die, but long live testing!
<b>分享者簡介:</b>
劉朋,諾基亞程度研發中心軟體研發經理,從事軟體研發8年,做過軟體工程教練,靈活教練,緻力于探索大規模軟體中高效能團隊進化之路。
中生代技術群微信公衆号