l

2017年3月17日 星期五

BDD(18)這是一個End-To-End的Scenario嗎?

March 17 08:58~10:40

屏幕截图 2017-03-17 10.34.52

 

考考你

敏捷開發是一種「價值驅動」的方法,為了交付價值給用戶,user story應該要表達成end-to-end。當stakeholder、PO、開發團隊透過討論之後寫出user story,接著舉出這個user story具體的例子之後,就可以進入開發階段,透過Cucumber、SpecFlow、JBehave、Fit/FitNess、Robot Framework等工具將此scenario自動化。

▼下圖是一個Cucumber的例子,鄉民們先把feature類比成user story(概念上feature的粒度較大,可能包含一個或多個user story),scenario就是feature(user story)的一個例子(example,一種執行路徑)。

屏幕截图 2017-03-17 09.02.06

 

從敏捷開發的角度來看,既然user story應該寫成end-to-end,那麼身為user story的一種執行路徑的scenario理論上應該也是end-to-end比較合理。針對這個問題,昨天在北科上「軟體生命週期管理」的時候Teddy問學生:「上面這個Scenario是一個End-To-End的Scenario嗎?

經過討論之後學生的看法分成兩派:

  1. 不是:這個scenario沒有描述使用者介面,使用者無法直接使用,所以不是end-to-end。
  2. 是:這個scenario描述「開三聯發票的系統行為」,雖然從字面上看起來並沒有提到使用者介面,但是使用者介面是一種實作細節,可以在step definition裡面描述。如此一來不管是透過網頁,或是透過手機App來實作這個scenario,都不用改修改它。

***

看似無聊但很重要

▼這個問題好像很無聊但實際上卻非常重要,因為它會影響落實BDD的方向,甚至是成敗的重要因素之一。依據BDD發明人Dan North對於BDD的定義:

屏幕截图 2017-03-17 09.35.30

 

首先看到outside-in這個字:由外而內,或是用更傳統的說法,由上而下(top-down)。看到由外而內很自然會認為BDD在描述scenario的時候應該從系統最外面,「也就是使用者介面」開始。所以在網路上或書上經常會看到類似的例子:

Scenario: Login

Given I am on the login page

And I input id as “John”

And I input password as “pwd321”

When I press the login button

Then I should be directed to the welcome page

接著在step definition裡面就看到實作程式碼呼叫Selenium開啟網頁,選擇DOM的某個元素,輸入Scenario中所描述的帳戶、密碼(在這裡是John/pwd321),然後再按下login按鈕,最後驗證網址跳到welcome 頁面。

這種例子如果是從介紹「工具」,例如Cucumber、SpecFlow、Selenium的角度來看,是很簡單易懂的好例子,但從BDD的角度來看,就不是那麼合適。因為BDD強調透過stakeholder、PO、開發人員的溝通來建立起「通用語言(Ubiquitous Language)」,這個通用語言正是後續開發活動以及living documentation(活的文件)的核心基礎。如果scenario都是從使用者介面切入撰寫,這樣的scenario頂多只是「自動化驗收測試」的文字版本,離「specification by example」還有一大段距離。

學過use case的鄉民可能還記得,撰寫use case的時候儘量不要相依於使用者介面,這個原則在BDD撰寫scenario的時候同樣適用。物件導向分析與設計(OOAD)透過use case來建立domain model(找出問題領域的重要概念,這些概念在設計階段會變成類別、介面、屬性、或關係)。同樣地,BDD透過scenario(例子)來建立domain model、介面、屬性、關聯。如果你的scenario都在描述使用者介面的元件,step definition裡面都在呼叫Selenium操作網頁元素,那十之八九你的BDD已經變成透過使用者介面驗證系統行為,你的「物件村(domain model)」很可能人丁單薄,很多商業邏輯不是寫在介面中,很可能就直接寫在資料庫中(stored procedure)。

***

所以哩?

針對以上的討論Teddy有幾點結論:

  • 為了專注於交付價值以及建立通用語言,BDD的scenario應該還是要保持end-to-end或是接近end-to-end。只不過end-to-end裡面關於前端,也就是使用者介面的細節,可以不要直接寫在scenario裡面,而是擺在step definition或是另外建立一層實作輔助層裡面
  • Outside-in(由外而內)並非一定要從使用者介面開始,它的意思應該是從任何你有興趣的事物外圍開始,然後逐步往內探索
  • Cucumber、SpecFlow、JBehave、Fit/Fitness這些工具只是支援BDD開發流程的一(小)環,並非全部。透過工具無法得知BDD的全貌。這也是為什麼《Specification By Example》這本書完全沒有從工具面去討論SBE/BDD要怎麼做,而是把重點放在7個流程模式( process pattern)
  • 你在撰寫use case所曾經犯過的錯誤,絕大部分在用Given-When-Then撰寫Scenario的時候也都可能再次出現。
  • 只要是以物件導向的方式開發軟體,modeling的技能都是重要的。採用BDD/TDD不會讓你自然產生好的domain model。

***

友藏內心獨白:OOAD的知識還是很有用。

 

延伸閱讀

沒有留言:

張貼留言