前言
哈嘍,大家好,我是海怪。
在做前端測試時,選用合適的測試策略遠比一通猛狂測試更重要,所謂 “方向 > 努力”。
如果選擇了錯誤的測試策略,很容易寫出維護性差和不穩定的測試用例。一旦業務出現變化,用例就全崩了。可能這也是大家討厭寫測試的原因之一吧。
Kent C. Dodds 在這篇文章 [《Common Testing Mistakes
》](https://kentcdodds.com/blog/c... "《Common Testing Mistakes》") 分享 了 3 個他看到的測試誤區。今天,就把這篇文章分享給大家吧~
翻譯中會盡量用更地道的語言,這也意味着會給原文加一層 Buf,想看原文的可點擊 這裏。
正片開始
誤區一:測試代碼的實現細節
説實話,我非常喜歡這個誤區(詳情可以看這裏),因為在測試過程中,它是一個很嚴重的問題,這樣寫測試也不會帶給你對應的信心。下面是一個測試代碼實現細節的例子:
// counter.js
import * as React from 'react'
export class Counter extends React.Component {
state = {count: 0}
increment = () => this.setState(({count}) => ({count: count + 1}))
render() {
const {count} = this.state
return <button onClick={this.increment}>{count}</button>
}
}
// __tests__/counter.js
import * as React from 'react'
// 用 React Testing Library 是很難測代碼實現細節的,所以這裏用 enzyme 來測
import {mount} from 'enzyme'
import {Counter} from '../counter'
test('the increment method increments count', () => {
const wrapper = mount(<Counter />)
// 千萬別這麼做
expect(wrapper.instance().state.count).toBe(0)
wrapper.instance().increment()
expect(wrapper.instance().state.count).toBe(1)
})
為什麼説上面是在測代碼實現細節?以及,為什麼測代碼細節是不好的呢?像上面那樣過度測試實現細節會帶來兩個結果:
- 我可以在測試完全通過的情況下弄崩業務代碼(比如在
onClick賦值時故意寫錯變量名) - 我可以在重構業務代碼的時候弄崩測試用例(例如,把
increment重命名為updateCount,測試就崩了,但業務代碼是能正常運行的)
(譯註:作者對重構的理解是:改動業務代碼邏輯時,測試代碼不應該做改動的,因為業務邏輯沒變,只是實現方式變了)
類似這樣的測試用例是最難維護的,因為你要不斷地更新它們(基於上面第二點),同時,它們也不會給你帶來更多代碼的信心(基於上面第一點)。
誤區二:100% 代碼覆蓋率
另一個誤區就是強求 100% 的代碼覆蓋率。 有趣的是,我經常看到在一些項目裏會被強制要求 100% 的覆蓋率。不管這種規定是從哪來的,這其實都是對代碼覆蓋的誤解,因為這樣並不能給你帶來相與之對應的代碼信心。
代碼覆蓋只能告訴你一件事:
- 這行代碼有被測試用例跑過
然而,它沒有告訴你的事有:
- 代碼是否按業務需求來正常工作
- 代碼是否能和項目裏其它代碼一起工作
- 項目崩了的時候會發生什麼(這裏指意外崩潰)
代碼覆蓋率的另一個問題是:每增加一行代碼的覆蓋,整體覆蓋量也會被增加。也就是説,如果你想提高整體覆蓋率,那麼在 “支付頁” 添加測試和在 “關於” 頁添加測試的效果是一樣的(整體覆蓋率變高了)。比這更嚴重的另一個問題是:這樣的覆蓋率不能讓你深入地瞭解你的項目...
目前來説,還沒有一種萬能的解決方案來獲得準確的代碼覆蓋率,畢竟每個項目的需求是不同的。我一般不會過度關注代碼覆蓋率,而是更關注於項目裏重要的部分是否覆蓋到位。在確定項目中的關鍵部分之後,我會利用覆蓋率報告來找出還未被測試覆蓋到的邊界情況。
聲明一下,對於開源模塊來説,100% 代碼覆蓋率是完全合理的,因為它們一般更容易達到 100% 覆蓋率(項目不大,而且相對簡單),而且他們都是很重要的代碼,會被很多別的項目引用。
誤區三:重複測試
相比於集成測試和單測,大多數人吐槽 E2E 最多就是很慢和不可靠。 你是不可能讓單個 E2E 測試既能跑得快,又能像單測那樣穩定的。反正就是不可能的。不過話説回來,單個 E2E 測試會比單測帶來更多代碼信心。在很多情況下,單測是不能像 E2E 那樣帶來那麼高的代碼信心的,所以項目中寫點 E2E 測試是肯定值回本的!
當然,上面這麼説不代表我們不能讓我們的 E2E 測試跑更快和變得更可靠。其中,重複測試是人們寫 E2E 測試時經常踩的一個坑,這會讓降低整個測試的性能以及可靠性。
我們應該要在隔離環境下執行測試。 理論上,每個單獨的 E2E 測試在執行時都應該像不同的用户使用軟件一樣。這樣的話,每次跑測試都要走一遍註冊登錄流程來創建新用户了,對吧?看起來好像是對的,然後你每次就要點點按鈕,輸入用户信息來做註冊登錄。這麼做只是為了業務中要用一下用户的登錄態,是吧?錯!這是不對的!
讓我們回過頭來想:為什麼要寫測試?因為這樣你可以交付出更有自信、不容易崩潰的項目呀!假如,你有 100 個測試需要用已登錄的用户來執行。那你應該要跑多少次註冊/登錄流程來讓你相信代碼是沒問題呢?100 次還是 1 次?正常人都會選 1 次,因為只要 1 次成功,處處都應該成功。因此,剩下的 99 次額外的測試並不會給你帶來任何代碼信心。它們只是在做無用功。
那你應該怎麼做呢?既然我們已經搭建好了測試的隔離環境,那麼就不應該在測試之間共享同一個 user。我推薦的做法是:當每次要註冊和登錄新用户時,在項目中發送同一個 HTTP 請求!發送請求肯定比在頁面點擊選中輸入框和輸入用户名、密碼來得更快,而且會產生更少的假錯誤 (譯註:假錯誤是指:測試失敗了,但是其實應用代碼本身沒任何問題) 。只要你能保證有 1 個能完整跑通註冊/登錄的流程,那麼你就不會失去這個登錄註冊流程的信心。
總結
一定要時刻記住我們寫測試是為了提高代碼信心。如果你現在做的事不能讓你提高對代碼的信心,那可以考慮你是否真的要這麼做!
好了,這篇外文就給大家帶到這裏了。這篇文章主要列舉了 3 個誤區:避免過度測試代碼細節、避免 100% 覆蓋以及避免重複測試。這三個誤區的產生都是因為我們沒有搞清楚測試的本質:提高代碼自信。當你很痛苦地編寫測試用例的時候,那麼很可能你鑽入了牛角尖,往錯誤的方向寫測試了,這時就要停止然後回過頭來想:怎麼做才能提高代碼自信呢?
如果你喜歡我的分享,可以來一波一鍵三連,點贊、在看就是我最大的動力,比心 ❤️