TDD 的原理和使用場景
前言
哈嘍,大家好,我是海怪。
說起前端測試,有一個東西肯定是逃不掉的,那就是 TDD —— 測試驅動開發。很多前端大佬也都非常喜歡用 TDD 的模式來編程。因爲它不僅可以通過測試保障代碼質量,還能創造一個良好的開發環境來提高開發效率。
然而,有些同學會對此嗤之以鼻,覺得先寫測試再寫業務不是浪費了那 50% 的工時麼?根本沒時間寫業務代碼呀。我覺得這部分同學其實並沒有搞清楚 TDD 的適用場景以及它要解決的問題。正好 Kent C. Dodds[1] 在他這篇 《When I follow TDD》[2] 裏聊了關於 TDD 的一些想法和思路,今天就把這篇文章分享給大家~
翻譯中會盡量用更地道的語言,這也意味着會給原文加一層 Buf,想看原文的可點擊 這裏 [3]。
正片開始
測試驅動開發(TDD)包含了 3 個步驟,一般也被稱爲 “紅,綠,重構循環”。
下面是它的工作原理:
-
🚨 紅色部分:在你還沒添加新功能前先寫一個測試。然後你會得到一個失敗的測試用例(會看到 “紅色” 的報錯信息)。
-
✅ 綠色部分:慢慢添加業務代碼來讓測試通過(看到 “綠色” 成功信息)。
-
🌀 重構部分:再回過頭看審視自己的代碼,把它重構成高可讀性和高維護性的代碼(這一步最棒的地方在於之前寫的測試用例會告訴你在重構時是否會破壞現有邏輯)。
-
🔁 重複:這就是個循環,反正 😉 一直走下去,直到寫完這個功能
在真實使用上,這個方法可能有所不同,有些人還會把 TDD 作爲自己的開發信仰。而我會站在更實用的角度上使用 TDD,只在一些我覺得有好處的情況下使用它。
那麼問題來了:“什麼時候用 TDD 纔是合理的呢?”。這其實很依賴你的開發直覺。坦率地說,這跟你用 TDD 的感覺和經驗有很大關係。當然,也有一些我經常會用 TDD 的經典場景。
修 Bug 場景
當在修 Bug 時,我喜歡在修復之前先寫一個測試來複現它。這麼做可以給我帶來非常大的信心,讓我在通過測試後馬上知道是什麼原因導致的這個 Bug,這樣一來,我就知道我實際上已經修復了這個錯誤,而不僅僅是圍繞這個問題進行了測試。
在維護我比較關注的軟件時,90% 的時間都遵循這種方法(並因此添加了測試)。特別是在我的開源項目中就這麼做的。這是這類測試的一個例子。
要修 Bug 麼?試試 TDD 吧。
純函數場景
我不會測所有的工具純函數(對大部分純函數我會用集成測試來覆蓋),不過,如果某個工具函數有足夠的複雜度,而且必須要用隔離的單測來測,那這也是一個使用 TDD 的絕佳機會。一般這類函數,你代碼裏都會有定義比較清晰的輸入和輸出結構。
我想大多數人都經歷過這樣的情況(就算現在沒有,以後會也有的)。以前我在 PayPal 的時候,我要在用戶輸入對應的金額準備轉賬時做格式轉換。由於要考慮貨幣的精度,這個處理邏輯比你相像得要複雜得多(有的貨幣根本沒有小數概念)。對貨幣金額做格式化就是一個做 TDD 很好的例子,因爲輸入和輸出都是很容易想出來的。
另一個很好的例子就是 我的項目 rtl-css-js 的測試(這也是開源的)。
要準備寫純工具函數麼?試試 TDD 吧。
定義良好的交互場景
直到我創建了 Testing Library[4] 後,我才認爲用戶界面的 TDD 在 Web 上確實可行,因爲:
當你在 測代碼實現細節 時,做 TDD 是沒有意義的。
老實說,如果你在測代碼實現細節,做任何測試都是沒有意義的(它們只會拖慢你的速度)。TDD 一部分的意義在於幫助你思考:如何從在不考慮細節情況下從外部構建你的應用,這樣你就會在設計項目時盯住你的主要目標,而不會鑽入牛角尖。當你知道要做什麼而不是想知道要怎麼做的時候,它會對你有所幫助。
在 Testing Library 出來前的一些流行工具(所有測試工具種類),它能夠讓你(鼓勵你)去測實現細節。如果這時你要用 TDD,你就得知道(比如)你要創建一個叫 makeDonation
的私有方法,調用時,它會分別傳入(而不是傳反) amount
和 currency
兩個參數。這也導致人們總感覺做 TDD 純屬浪費時間,只是走走過場。
不過現在 Testing Library 可以讓你關注於用戶交互,而不是實現細節,你可以在設計和定義好用戶交互後使用 TDD。
幾年前我錄的一個視頻, 裏面用 Login
組件展示了這樣的方法。這已經是幾年前的了,現在應該更容易實現。
要準備設計一個定義明確的 UI 麼?試試 TDD 吧。
總結
到這裏說差不多了。我敢肯定,其他人在做 TDD 實踐時也有他們自己覺得合理的場景,這也挺好的。
如果我只是寫點試驗代碼片段(我經常這麼幹)或者只是亂寫寫代碼,那我肯定不會用 TDD 的。只有在項目在往正道發展時,我纔會添加對應的測試。順便說一下,我在使用類型檢查工具時也是這麼幹的。這也是我一直遵循的 抽象思路。
寫測試,添加類型定義,對代碼做抽象都是對你項目的投資。如果你不確定創建的東西是否會長期存在,那麼進行這些投資是沒有意義的。如果你不確定在你完成時你創造的東西最終會變成什麼樣,那麼這些投資也可能是不明智的。還有就是這些錯誤的投資所造成的沉沒成本最終也會淪爲一些不優雅的解決方案,最終會影響你的一些判斷。
好了,這篇外文就給大家帶到這裏了。文章裏主要講了 3 種使用 TDD 的場景:修 Bug 時,寫純函數時,以及設計 UI 時。我感覺在寫純函數(數據轉換),以及寫接口時(Node 端開發)時用的比較多,修 Bug 嘛,實際情況都是業務 Bug,要用測試復現是比較麻煩的。設計 UI 前寫測試也是比較麻煩的。總之,大家應該都會有自己使用 TDD 的場景,找到適合自己的就好。需要注意的是,千萬別提前做優化,特別是你還不確定你的項目要發展到什麼程度時。
如果你喜歡我的分享,可以來一波一鍵三連,點贊、在看就是我最大的動力,比心 ❤️
參考資料
[1]
Kent C. Dodds: https://kentcdodds.com/
[2]
《When I follow TDD》: https://kentcdodds.com/blog/when-i-follow-tdd
[3]
原文: https://kentcdodds.com/blog/when-i-follow-tdd
[4]
Testing Library: https://testing-library.com/
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/J6sVc91YaaUnTtGcueb6oA