為什麼我不做 TDD? - Shai

編寫大量的測試。這怎麼可能是壞事呢?

但隨著時間的推移,我從另一個角度看待它。我認為它是一個非常有限的工具,有非常具體的用例。它不適合我所建立的專案型別,而且經常阻礙它應該促進的流動過程。

在TDD其中,我們需要定義約束條件,然後解決問題。

這種方法真的比“先解決問題然後驗證約束條件”好嗎?

這就是“TDD”與“只寫好測試覆蓋”的核心區別。

1、TDD好處

TDD是一種有趣的方法。它在處理鬆散型別的語言時特別有用。在這些情況下,TDD是非常好的,因為它填補了一個嚴格的編譯器和linter的角色。

在其他情況下,它也有意義。當我們在構建一個有非常明確的輸入和輸出的系統時。我在構建課程和教材時遇到過很多這樣的情況。在處理真實世界的資料時,當我們有中介軟體處理資料並以預定的格式輸出時,這種情況有時會發生。

我們的想法是用中間的隱藏變數來構建方程。然後,編碼就變成了填入方程。在這樣的情況下,這是非常方便的。

編碼變成了填空。

2、TDD壞處

“測試驅動開發是一種複式記賬法。同樣的紀律;同樣的推理;同樣的結果”。- 鮑勃-馬丁大叔

我想說的是,

測試有點像複式記賬法

是的。我們應該有測試。

問題是我們應該在測試的基礎上構建我們的程式碼,還是相反?

這裡的答案並不那麼簡單。

如果我們有一個預先存在的有測試的系統,那麼TDD就有了所有的意義。

但是

測試一個還沒有建立的系統:

有一些情況是有意義的,但不像人們想象的那樣經常有意義。

TDD的主要主張是 “其設計”:

測試實際上是一種系統的設計,然後我們實現這個設計。

這樣做的問題是:我們也不能對設計進行除錯。在過去,我曾為一家大型日本公司做了一個專案。這家公司有一套最大、最詳細的附件設計書。基於這些設計規範,公司建立了成千上萬的測試。我們應該用我們的系統透過大量的測試。請注意,大多數甚至不是自動的。

這些測試都有錯誤:有許多競爭性的實現,但他們都沒有發現測試中的錯誤。

為什麼呢?

他們都使用相同的參考實現原始碼:這使得程式碼中的這些錯誤長期存在,其中一些是嚴重的效能錯誤,影響了所有以前的版本。

我們是第一個跳過這一點完成乾淨實現的團隊。

但真正的問題是進展緩慢:

公司無法快速前進。TDD的支持者會很快評論說,一個TDD專案更容易重構,因為測試給了我們一個保證,我們不會有迴歸的問題。但這適用於事後進行測試的專案。

3、更糟糕的是

TDD在很大程度上關注快速單元測試。在TDD系統上執行緩慢的整合測試或可以通宵執行的長期測試是不現實的。你如何驗證大規模系統並能整合到一個主要系統?

在一個理想的世界裡,所有的東西都會像樂高積木一樣點選到位。但是我並不生活在這樣的世界裡,整合測試失敗得很厲害。

這些是最糟糕的失敗,也是最難追蹤的錯誤。

我更希望在單元測試中出現這些故障,這也是為什麼我會進行單元測試的原因:Bug很容易修復。但即使有完美的覆蓋率,它們也不能正確地測試互連。

我們需要整合測試,它們能發現最可怕的bug。

結果,TDD過度強調了 “不錯的 ”單元測試,而不是必不可少的整合測試。

是的,你應該兩者都有。但我必須有整合測試。那些測試並不適合TDD過程。

4、權利驅動的測試

我寫測試的方式是在個案基礎上選擇的。如果我有一個案例,提前測試是很自然的,我就會使用這種方式。但對於大多數情況,先寫程式碼對我來說似乎更自然。在寫測試時,審查覆蓋率數字是非常有幫助的,這是我在事後做的事情。

正如我之前提到的,我只檢查整合測試的覆蓋率。我喜歡單元測試,並監測那裡的覆蓋率,因為我也希望那裡有好的覆蓋率。但是對於質量來說,只有整合測試是重要的。一個PR需要單元測試,我不關心我們是否在實現之前就寫好了。我們應該判斷其結果。

4、糟糕的自動化

當特斯拉在建立他們的Model 3工廠時,他們進入了生產地獄。問題的根源在於他們試圖將一切都自動化。帕累託原則完全適用於自動化。有些事情對自動化非常抗拒,使整個過程變得非常糟糕。

其中真正失敗的一點是在UI測試中。像Selenium等解決方案在測試Web前端方面取得了巨大的進步。然而,複雜性是巨大的,測試是非常脆弱的。我們最終得到的是難以維護的測試。更糟的是,我們發現UI更難重構,因為我們不想重寫測試。

我們可能可以跨越80%的測試功能,但是對於自動化來說,有一個收益遞減的點。在這些環境中,TDD是有問題的。功能是容易的,但建立測試變得難以維持。

最後

我不反對TDD,但我不推薦它,而且實際上我不使用它。

當從測試開始有意義時,我可能會這麼做,但這不是真正的TDD。我是根據結果來判斷程式碼的。TDD可以提供很好的結果,但往往它過分強調單元測試。從長遠來看,整合測試對質量更重要。

自動化是偉大的。直到它停止。有一個點,自動化測試只是沒有什麼意義。接受這一點,並將我們的努力集中在一個富有成效的方向上,會節省我們大量的時間和精力。

這是我作為一個喜歡型別安全的嚴格語言的Java開發者的偏見。像JavaScript和Python這樣的語言由於其靈活性,可以從大量的測試中受益。因此,TDD在這些環境中更有意義。

總而言之,測試是好的。但TDD並不能帶來更好的測試。如果它對你有用的話,這是一個有趣的方法。在某些情況下,它是巨大的。但是,認為TDD是必不可少的,甚至認為它將大大改善所產生的程式碼的想法,是沒有意義的。

更多:為什麼我不做 TDD? - Shai