淺談測試驅動開發TDD之爭

前言

在歷史上有很多精彩絕倫的神仙打架,比如數學界的牛頓和萊佈尼茨關於微積分的曠世之爭;比如量子物理中的愛因斯坦和波爾的紫禁之巔;比如足球裡的梅西和C羅的旗鼓相當難分高下;又比如滴滴和快滴之間觸目驚心的燒錢大戰……而在軟件行業中,也同樣有神仙打架的名場面,那就不得不提的是2014年的那場——測試驅動開發(TDD)之爭。

比賽的紅方是David Heinemeier Hansson,藍方是Kent Beck。David Heinemeier Hansson 由於名字較長簡寫成DHH,Ruby on Rails 正是出自於DHH之手。而這場打架還加入瞭“裁判”員——Martin Fowler,在比賽中Martin Fowler記錄瞭紅藍雙方的每一次組合拳、上勾拳、側踹、抱摔……總結如下:

紅方DHH觀點

1.許多推動TDD的開發人員會讓你覺得:如果你不使用TDD的話,你的代碼就是骯臟的。

2.由單元測試開始驅動你的設計並不是一個好的主意。

3.TDD的概念“測試必須夠快”是目光短淺的。

4.對TDD的依賴會導致徹底忘記系統測試。

5.關註並且隻關註單元模塊並不能有助於創建一套完美的系統。

6.100%的覆蓋率是愚蠢的。

7.程序員希望軟件是一門科學,可是它並不是。它更像是創造性的寫作活動。

8.優秀的軟件並不像工程學那樣,它更像寫作。清楚簡潔的寫作要優於復雜晦澀的寫作。

9.清晰是有好處的,好到應該將清晰性作為第一目標,而非測試覆蓋度或者測試速度。

10.成為一名優秀的開發人員就像成為一名優秀的作傢一樣困難。

11.就像寫作一樣,成為優秀的程序員的辦法就是以清晰為目標從而大量編寫軟件、大量閱讀軟件。

藍方Kent Beck觀點

DHH已將TDD委托給歷史垃圾堆。我很難過,不是因為我就把它從歷史的垃圾堆中拯救出來,而是因為現在我需要雇傭新技術來幫助我解決編程過程中的許多問題:

1.過度工程化。我傾向於“投入”我“知道”我“將需要”的功能。使一個紅色的測試變為綠色(以及未來的測試列表)有助於我實現足夠的功能。我需要找到一個新的方法來保持專註。

2.API反饋。我需要找到一種新的方法來獲得關於我的API決策的快速反饋。

3.邏輯錯誤。我需要找到一種新的方法來抓住那些我很容易犯的討厭的測試錯誤。

4.文檔。我需要找到一種新的方式來傳達我對api的期望,並記錄我在開發過程中的想法。

5.感到不知所措。我真的會懷念如何使用TDD,即使我無法想象一個實現,我幾乎總能想出如何編寫測試。我需要找到一個新的方法,以便下一步上山。

6.將接口與實現思想分離。我傾向於用實現推測來污染API設計決策。我需要找到一種新的方法來分離這兩個層次的思維,同時在它們之間提供快速的反饋。

7.協議。我需要找到一個新的方法,精確地與一個編程夥伴關於我正在解決的問題。

8.焦慮。也許我最懷念的是TDD給我的瞬間“一切都好嗎?”按鈕。

9.我相信我會找到其他方法來解決這些問題。及時。疼痛會減輕的。再見TDD,老朋友。

神仙打架不虧是神仙打架,從那以後業界關於測試驅動開發的觀念也分成瞭兩派。一派主要來源自像國內的一些互聯網等項目中聲音——需求的迭代和更新之快,要求公司或團隊能快速交付有價值的產品,而TDD對於很多開發人員來說無疑是帶來瞭繁重的工作壓力和交付壓力。甚至有人開玩笑話說:“ Deadline Driven Development 才是第一生產力 ”。

當然也有人力挺TDD,“TDD並沒有死。很明顯,既然它有這麼這麼多的支持者,它怎麼可能會死呢? 這就像在問,設計模式死瞭嗎?或者功能性自動化死瞭嗎?不,它並沒有死。而且它在將來任何時候都不會死亡。它將來可能會變成其他一些新的事物、甚至是一些更好的事物,但是它永遠不會死亡。所以讓我們跳過這一部分吧。”

關於測試驅動開發說瞭這麼久,那麼測試驅動開發到底是個啥呢?

測試驅動開發(TDD)是什麼

測試驅動開發,英文全稱Test-Driven Development,簡稱TDD,是一種不同於傳統軟件開發流程的新型的開發方法。 它要求在編寫某個功能的代碼之前先編寫測試代碼,然後隻編寫使測試通過的功能代碼,通過測試來推動整個開發的進行。 這有助於編寫簡潔可用和高質量的代碼,並加速開發過程。

Kent Beck:“測試驅動開發不是一種測試技術。它是一種分析技術、設計技術,更是一種組織所有開發活動的技術”。

分析技術: 體現在對問題域的分析,當問題還沒有被分解成一個個可操作的任務時,分析技術就派上用場,例如需求分析、任務拆分和任務規劃等,《實例化需求》這本書可以給予一定的幫助作用。

設計技術: 測試驅動代碼的設計和功能的實現,然後驅動代碼的再設計和重構,在持續細微的反饋中改善代碼。

組織所有開發活動的技術: TDD 很好地組織瞭測試、開發和重構活動,但又不僅限於此,比如實施 TDD 的前置活動包括需求分析、任務拆分和規劃活動,這使得 TDD 具有非常好的擴展性。

測試驅動開發(TDD)的目標

Kent Beck 在他的著作《Test-Driven Development》(見參考附錄)一書中提到:“代碼簡潔可用這句言簡意賅的話,正是 TDD 所追求的目標”。

對於如何保證“代碼簡潔可用”可以使用分而治之的方法,先達到“可用”目標,再追求“簡潔”目標。

可用: 保證代碼通過自動化測試。

代碼簡潔: 在不同階段人們對簡潔的理解程度也不一樣,不過遵循的原則差不多,例如 OOD 的 SOLID 原則(詳見參考附錄),Kent Beck 的 Simple Design 原則(詳見參考附錄)等。

雖然有很多因素妨礙我們得到整潔的代碼,甚至可用的代碼,無需征求太多意見,隻需要采用 TDD 的開發方式來驅動出簡潔可用的代碼。

測試驅動開發(TDD)的規則

在TDD 的過程中,需要遵循的三項原則:

1.在編寫好失敗的單元測試之前,不要寫任何產品代碼。

2.隻要有一個單元測試失敗瞭,就不要再寫測試代碼。無法通過編譯也是一種失敗。

3.產品代碼恰好能夠讓當前失敗的單元測試成功通過即可,不要多寫。

測試驅動開發(TDD)的流程

測試驅動開發是一個過程,依賴於不斷重復極短的開發周期,這個周期也稱為“紅燈-綠燈-重構”,如上圖。簡單的來說,基於TDD的三項原則,TDD的這種步驟(周期)如下:

1.添加一個小的測試

2.運行測試並查看失敗

3.對測試進行微小的改動通過測試

4.運行所有測試並看到其通過

5.通過重構去掉重復部分

需要註意的是,不同階段有不同的目的,他們需要不同的解決方案,前二個階段需要很快地完成,以便知道新添加功能的狀態。為瞭達成這個目的,可以通過任何手段,因為僅在這時才這樣做,也是為瞭能快速完成好的設計。

測試驅動開發(TDD)的好處

TDD主要的好處主要包括瞭,確定性、重構代碼、單元測試即文檔。

確定性。TDD提升瞭單元測試的覆蓋率,在每輪迭代產品都會新增代碼,如果有一套覆蓋率很高( 90% 或更高)的單元測試,那麼隻需執跑一遍測試用例,那麼能成功交付的把握就會比較大。反之,如果覆蓋率越低,越需要更多的人力去進行手動驗證。 在 kent Beck的《測試驅動開發》舉的例子中,正因有瞭TDD才有勇氣和老板說我們可以做!這就是TDD最強大的地方,它讓你擁有一套值得信賴的測試,打消你對修改代碼的恐懼。

重構代碼。Martin Flower在他的《重構》中也指出,完善的單元測試是他進行重構的基石,從TDD的流程可以看到,重構是TDD的一部分,運用TDD的同時也推動瞭代碼的重構。

單元測試即文檔。在軟件行業裡,人員的變動的很頻繁的,如果要盡快熟悉某個模塊的業務邏輯。看文檔?程序員寫的文章一般都不太容易看,而且文檔經常會和代碼不同步,代碼修改瞭文檔沒跟著改的事情經常發生。看源碼?看完也不一定知道為什麼。如果這時候有一套非常完整的單元測試,那可能就是所有接手別人代碼的程序員的福音。首先,代碼不會撒謊,其次,測試用例明確告訴瞭你這個函數是做什麼的,什麼輸入對應的都有什麼預期輸出。單元測試就是最好的底層文檔,哪個專業人士不想提供這樣一份文檔呢?

此外,TDD還能夠促成良好的代碼設計。由於你先寫測試代碼,你會盡可能的讓代碼調用起來更加簡單方便,這也就促使你去考慮如何更好的設計代碼。以避免會出現一個函數裡實現的功能過多,或者和其他代碼過於耦合而無法測試的情況。

當然測試驅動開發除瞭好處以外,還有神仙打架中紅方代表DHH所提出的一些問題。總結來看,關於TDD的爭議可以大致從這幾個方面來看,軟件開發應該由什麼來驅動,測試的速度和覆蓋程度,以及設計思想層面等幾方面。從 辯證統一的角度來看,事物有兩個方面, TDD不一定能適用於所有的場景,同樣TDD的局限性在某些場景下也不見得是對的,如果想要能更好的適用於自身,不僅要拿捏好度的問題還要以敏捷的思想來應對問題,比如不應該盲目的制定100%或0%的測試覆蓋率,也不應該固化開發步驟而不顧實際情況。

所以,在最後的神仙打架中,Kent Beck也表達瞭David的論述可能會讓TDD浴火重生、鳳凰涅槃的觀點,希望可以找到更加好的方法。但無論如何, 在我們實際工作中,不應該因為某些 觀點成為我們接受或者拒絕它的理由。正所謂大道甚夷,而民好徑,作為敏捷開發中的一項優秀實踐來看,TDD隻有在真正使用過後才能評價是否已死的問題。那麼你在踐行敏捷開發的時候,是否使用過TDD這種實踐呢,又或是踐行過其他一些敏捷開發的實踐呢,有沒有評測過你所在的項目中的敏捷開發的成熟度是如何的呢?

沒有那就對瞭!華為雲的DevCloud專業服務正是為此而生!

針對不同的崗位提供瞭評估的能力,讓開發者可以對號入座,並基於你所在的崗位、技術得到客觀、全面、系統的測評以及名師般的學習引導。快來訪問專業服務平臺,通過個人能力評估,看看自己是什麼水平吧!

以上就是淺談測試驅動開發TDD之爭的詳細內容,更多關於測試驅動開發TDD之爭的資料請關註WalkonNet其它相關文章!

推薦閱讀: