你的老闆不會欣賞 TDD:試試這個行為驅動的開發示例
已發表: 2022-03-11測試。 它經常被留到最後一分鐘,然後因為你沒有時間、超出預算或其他任何原因而被削減。
管理層想知道為什麼開發人員不能“一次就做好”,當不同的利益相關者描述系統的不同部分時,開發人員(尤其是在大型系統上)可能會措手不及,例如盲人描述系統的故事。大象。
然而,不可避免的是,每個項目的第一步都是討論要構建的軟件或功能的行為。 客戶或業務人員找到開發團隊中的某個人並解釋他們想要什麼。
有時這些交互以敏捷用戶故事的形式出現。 有時它們以設計文檔的形式出現,例如 Chris Fox 去年的博客條目。 它們也可以作為 Keynote 中的流程圖或模型,甚至是匆忙的電話。
僅從這些通信中,開發人員負責構建一個“正常工作”的系統。 這對於在更大系統之外工作的自由職業者來說尤其困難。
為什麼測試會被削減?
這裡有一個明顯的差距:如果業務所有者在一開始就設想了系統的行為,那麼為什麼測試這些行為是否真正有效通常是被削減的步驟?
答案可能非常簡單:測試通常不被視為共享資本; 他們不被認為對項目有價值,因為“他們只是為工程師服務的”,或者類似地,為單個部門或一組人提供價值。
我們如何對這些共享資本、系統行為列表進行測試? 不僅包含測試驅動開發 (TDD),還包含行為驅動開發 (BDD)。
什麼是 BDD?
行為驅動開發應該關注你的代碼正在實現的業務行為:代碼背後的“為什麼” 。 它支持以團隊為中心(尤其是跨職能)的工作流程。
當開發人員和敏捷產品所有者或業務分析師坐在一起並在純文本編輯器中編寫待定規範(稍後由開發人員填寫)時,我已經看到敏捷 BDD 工作得非常好:
- 業務人員指定他們希望在系統中看到的行為。
- 開發人員根據他們對系統的理解提出問題,同時從開發的角度寫下所需的其他行為。
理想情況下,雙方都可以參考當前系統行為列表,看看這個新功能是否會破壞現有功能。
我發現這個簡單的行為給了我足夠的約束,我可以像開發人員一樣思考:“鑑於我必須實現這些測試,這如何將我/每個人限制在我可以在代碼中實現的規範中”? 由於它們是待定規範,因此它們可以快速輕鬆地在大量協作中編寫。
這種協作方法讓我專注於該功能為最終用戶提供的功能,而讓業務人員在場限制我談論行為,而不是實施。 這突出了 BDD 與 TDD 的差異。
讓我們看一個行為驅動開發的例子
場景:您是負責公司會計系統的團隊中的開發人員,該系統在 Rails 中實現。 有一天,一位業務人員要求您實施一個提醒系統,以提醒客戶他們的待處理髮票。 因為您正在按照本教程練習 BDD; (相對於 TDD),您與該業務人員坐下來開始定義行為。
您打開文本編輯器並開始為業務用戶想要的行為創建待定規範:
it "adds a reminder date when an invoice is created" it "sends an email to the invoice's account's primary contact after the reminder date has passed" it "marks that the user has read the email in the invoice"
這種對開發過程中行為的關注使得測試可以用來驗證您正在構建正確的功能,而不僅僅是您的代碼是否正確。 請注意,措辭是商業語言,而不是系統的內部實現語言。 您不會看到或關心發票是否belongs_to
某個帳戶,因為開發團隊之外沒有人關心這一點。
一些開發人員更喜歡現場編寫測試用例,調用系統中的方法,設置期望,如下所示:
it "adds a reminder date when an invoice is created" do current_invoice = create :invoice current_invoice.reminder_date.should == 20.days.from_now end
測試套件將失敗,因為我們還沒有編寫代碼來設置reminder_date
。
相對於失敗的規格
我了解編寫失敗規範的開發人員,但有業務人員在我身邊,這對我來說從來沒有用過。 錯誤的業務人員要么被細節分心,要么接受這些新知識並嘗試對開發人員更了解的事物進行微觀管理(正確的數據庫設計、代碼重用)。
以我的經驗,對特定行為寫不止一行的概述會讓商務人士感到厭煩。 他們會認為這是對他們時間的不當利用,或者會急於描述他們想到的下一個行為。
BDD 與 TDD 有何不同?
讓我們以不同的方式看待這個問題,使用測試驅動的開發方法,並寫出待處理的測試:
it "after_create an Invoice sets a reminder date to be creation + 20 business days" it "Account#primary_payment_contact returns the current payment contact or the client project manager" it "InvoiceChecker#mailer finds invoices that are overdue and sends the email"
這些測試很有幫助,但只對一組人有幫助:工程師。 BDD 對於與跨職能產品團隊的每個成員進行溝通非常有用。

您當然可以在 BDD 思維模式下通過使用未決行為進行測試優先開發。 首先,編寫測試; 然後運行它(紅色); 然後讓它工作(綠色); 然後讓它正確(重構)。
BDD 社區中的大量工作已使測試中的斷言檢查讀起來像英語。 這是一個典型的 RSpec 測試:
a = 42 a.should == 42
這種格式使以後更容易閱讀。 但請記住,這不是我們在這裡所做的——關鍵是盡快降低行為——並執行“每個規範一個測試行為”的原則。 理想情況下,待定規範標題應該告訴您正在測試什麼。
BDD 不是用花哨的方法來驗證你的結果。 這是關於在團隊的所有成員之間分享預期的行為。
行為驅動的開發是關於協作和溝通
讓我們回到我們的場景:研究公司會計系統。
您與業務人員一起了解項目的功能,通過其內部分析系統(對像如何在內部組合在一起),然後他們從外部分析系統。
您想到一些條件,並詢問業務分析師在以下場景中會發生什麼:
* What's the default reminder date going to be? How many days before the invoice due date? * Are those business days or just calendar days? * What happens if there's not a primary contact associated with the account?
你得到答案。 重要的是,業務人員要明白,您並不是要在他們的寵物想法中打洞,或者過於迂腐。
通過這種方式,行為驅動開發是一個幫助協作並開始兩個部門之間對話的工具。 這也是一種闡明所需功能範圍並從開發團隊獲得更好估計的方法。 也許您意識到從給定的時間點開始計算 10 個工作日是不可能的; 這是您需要實現的附加的、單獨的功能。
開發人員會有開發人員的考慮(“你說‘day’到底是什麼意思?”),而業務人員會有自己的考慮(“請不要在這裡使用過期這個詞,這意味著不同的東西”)。 讓一組或另一組去嘗試自己編寫這些業務邏輯行為測試(Cucumber 的承諾)會削減每一方的有價值的輸入。
當敏捷客戶不再實際在房間裡時,它也是一個很好的替代品:將他們的願望寫在紙上,與開發人員對您正在構建的內容的分析(和翻譯)相結合。
設計文件
較早的 Toptal 博客文章 Chris Fox 談到了設計文檔,尤其是在項目開始時。 理解和提取業務行為的範圍從系統可以了解的項目縮減到需要數十年程序員年才能完成並擁有數百或數千個行為規範的項目。
Chris 的文章還提到了元素在屏幕上的行為,這是我經常與設計師產生分歧的一個領域:“這個按鈕在昏暗的時候是什麼樣子的”或者“這在 11 個屏幕上看起來如何”,因為這個頁面顯然是為 24 英寸屏幕設計的?” 這種與業務人員的反復來回可以發現項目的圖形資產或頁面佈局中的空白。
在非常大的跨職能團隊中,有許多團隊成員有自己的顧慮:設計師、開發人員、可能來自運營的人員、數據庫管理員——也許是 QA 人員(是的,TDD 和 BDD 中每個人都有自己的位置!),每個人帶著自己的顧慮和問題。 BDD 比測試驅動開發更能推動這種協作。 來自“當這個表的數據太大時會發生什麼?” 到,“嗯,這將是一個昂貴的查詢,我們想以某種方式緩存它”到,“等等,用戶應該看到所有這些機密信息嗎?”,可能不僅僅是開發人員和對此新功能有疑問的業務分析師
行為驅動開發是關於共享工件
什麼是共享工件?
我喜歡將軟件工程中的“工件”視為描述項目或項目團隊的潛在物理事物,並且可以在六個月後找到。 好的人工製品解釋了為什麼事情是這樣的。
走廊對話不是人工製品。 白板繪圖也不是。 白板繪圖變成了大而長的類文檔或設計文檔——這些都是人工製品。 會議紀要也是人工製品。
工件是保存到存儲庫或共享空間的一些源代碼,以及票證系統中的票證,或內部 Wiki 上的註釋,甚至是持久的聊天日誌。
在我看來,共享工件是最好的工件。 它們不僅展示了某些東西為什麼會這樣,還展示了它為什麼存在於應用程序中。
你如何在 BDD 中使用它們?
行為應該是一個共享的團隊工件——測試不應該只是程序員的忙碌工作! 雖然最好有一個整個團隊都可以輕鬆查看當前規範的系統(也許部署系統也會提取行為列表並將其保存到站點或 wiki 的私有區域),但您也可以手動執行每個短跑。
遊戲的名稱是“幫助開發人員創建我們需要的規範,以更快地交付業務價值、跨部門協作並做出更好的估計”。
這種全公司範圍內對系統功能的理解也是一種資本形式。 這是代碼“如何”的“為什麼”。
結論
我們如何解決交付給客戶的錯誤軟件問題? 通過確保測試不被視為“只有開發人員關心”的事情。
除了代碼正確性之外,描述和理解系統的需求還有很多好處:建立部門間對話並確保滿足所有利益相關者的關注(而不僅僅是擁有大頭銜的利益相關者)。 使用行為驅動開發從一開始就了解這些需求並測試整個團隊關心的外部業務行為——這是確保項目質量的好方法。