成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

淺析前端測試的反模式

開發 開發工具 前端
你的測試應該盡量少用函數去手動觸發,而要盡量多地利用測試框架給你的API,去模擬Input框的輸入,按鈕的點擊,表單的提交等等。

[[431928]]

過于關注實現細節的測試

在為前端項目編寫測試用例的時候,你也許和我一樣,曾遇到過以下困擾:

(1) 明明進行了功能正確的改動,測試卻掛了。修復測試有時候得認真閱讀各種mock的細節,或者去了解很多本沒有必要知道的代碼邏輯。最后修測試花的時間比進行業務改動花的時間還要長(甚至長很多)。

(2) 對代碼進行提取抽象之后,為各個組件或函數添加測試,實際上是用測試工具的API去重復 業務代碼的內部實現邏輯(有時候還很麻煩!)。任何正常的重構都會導致測試失敗,你本來希望測試能告訴你什么樣的修改是對的,結果現在測試只能告訴你代碼確實有被修改。

(3) 測試寫好,覆蓋率提高,本應信心十足地認為代碼變得健壯了,可是捫心自問,你知道自己寫的這個測試弱點在什么地方,或者說還有多少細節沒有涵蓋。你精心模擬了一個條件,去觸發邏輯流程,并且測試通過,可是在真實的瀏覽器交互中用戶也許并不能觸發這個條件。因此,同樣的道理,你在自己的代碼通過了他人寫的測試之后,也不能確定真實場景下沒有問題,只好把后續的重任交給QA。

造成上面三個問題的原因不止一個,但測試過于關注實現細節在我看來是最主要的。

第一個問題,明明是正確的改動,可是測試不止是驗證業務功能,還對實現細節提出了不該提出的要求,比如要求你的函數接受跟以前一樣的參數,返回值必須是字符串而不能是數組等等。可是這個函數只是實現流程中一個小小的環節,也許在下次重構時就會不復存在。

第二個問題很類似,如果測試代碼去重復實現細節,不管進行正確還是錯誤的重構,你都得把測試改一遍,那原先的測試又能提供什么價值呢?

第三個問題有時發生在,測試的實現細節,不能覆蓋整個真實交互流程的時候。用戶點擊的是屏幕上的button按鈕,而測試的起點是onClick事件被觸發。后面的邏輯被驗證成功,可問題偏偏發生在點擊環節,真實的點擊也許因為按鈕狀態而無法觸發onClick事件。

因此,才會有人提出前端的測試應盡量去模擬真實的用戶行為,Testing-Library就在其官網的“指導原則”章節,鼓勵使用者盡量仿照應用真實的使用方式去編寫測試,并明確提出,你的測試越接近用戶的真實使用方式,它就能給你越多的信心。換句話說,你的測試應該盡量少用函數去手動觸發,而要盡量多地利用測試框架給你的API,去模擬Input框的輸入,按鈕的點擊,表單的提交等等。

如此一來,有的函數,你也無需寫測試證明它的返回值如你所愿,需要寫的,是頁面顯示了期待的文字,發生了預期的變化,進行了對應的跳轉。你會發現,這時的測試就像寫在卡里的AC一樣。只要測試是通過的,你就有理由相信主體功能沒有破壞,而不只是函數工作正常。

沒有獨立業務含義的測試單元

看到上面的方案,你可能會立馬會想到一些問題。

首先就是測試流程可能會很長,從用戶填完表單,點擊提交,到期待的變化出現,當中可能經歷了好幾個函數的執行,連帶著一系列的副作用。模擬這一系列行為,似乎是集成測試與E2E測試該干的事情。如果項目中大部分邏輯都是由這種測試去覆蓋,看起來與測試金字塔所說的由單元測試作為地基是矛盾的。

我認為,當真實遇到的問題碰到了某種教條規范時,后者該適當地讓步。

鼓勵多寫單元測試的原因在于它們成本低,有針對性。可是在前端項目里面,很多形式上的單元并沒有獨立的業務含義。

拿React項目舉例,好多函數只是因為它們在形式上可以被抽取出來,就被拎到一個單獨的文件里,從而降低主函數的復雜度。如果給它寫單元測試,你就不得不手動觸發它的參數變化,或者檢測它的參數函數是否有被調用。

我們寫的React hook尤其如此。很多時候抽取自定義的hook是出于邏輯上的原因,把相關的邏輯和數據聚合到一起,減輕UI組件的負擔,但這些hook往往沒有一個可以輕易解釋清楚的業務含義,而且它們也不會被其它地方使用。

所以這類 “單元”只是長得像單元而已,它們其實只是一個實現環節。這里完整的UI操作流程,才更像一個有價值的單元,盡管它們在形式上可能超越了單個函數的范疇。

但我不想矯枉過正,確實有不少情況下,一個util函數,一個hook,一個很小的公共組件,都是有獨立存在的價值的,因此,它們也應當被視為真正的單元,確實“有資格”擁有自己的專屬測試。

testing-library下面有一個單獨的庫,叫react-hooks-testing-library,讓你無需通過UI行為層面,而是直接以hook的方式去測試它們。它的GitHub頁面上,明確提出了使用以及不使用它的場景:當你的hook不與組件強相關,擁有獨立含義時可以使用;當你的hook只被一個組件使用,且和它的定義強相關時,則不建議使用。

【插入一段:盡管存在react-hooks-testing-library這樣的工具,但像SWR這樣優秀的三方庫,在用testing-library為自己的hook API做測試的時候,依然選擇在UI層面進行。方法是,把自己的hook置于一個臨時的div標簽里進行render,把數據的變化映射成html文字的變化,最后對文字內容做斷言。其實對于獨立性強的函數,個人覺得放置在UI里面做測試倒沒有太大區別,但SWR的例子體現了對“仿照真實使用場景去測試”這一原則的尊重。】

將上面的規律套用到Angular項目中,也是類似的。對于獨立性和通用性不強的pipe,directive,reducer,effect,service,都可以認為它們是實現流程的一部分,從UI行為層面寫好測試即可。

總之,在構思前端測試的時候,與其死守“單元測試”的字面含義,不如結合實際場景,重新思考什么才是真正有價值的“單元”,因地制宜地去寫。換種角度表述,與其在意我們寫的測試是不是“單元測試”,不如追求更核心的東西——我們的測試有沒有以合適的方式去校驗邏輯。

另外,當我們的“單元”過大,一些邏輯可能就會覆蓋不上。像sonar這類工具,不僅會檢查你的行數覆蓋率,還會檢查你的各項條件語句是否有被測試執行。當一套測試的行為流程囊括了多個函數,而且每個函數都有好幾個if…else語句時,想要在UI操作與mock數據上把所有情況都覆蓋到,成本就會變得非常高昂。

對于此,我們得承認,無論用什么方式組織測試,覆蓋所有的條件分支都是不太現實的,而且價值也不大。對于“滿足條件A就執行XXX”之類的語句,條件為非A時沒有業務上的規定,如果為了刻意覆蓋函數的所有條件,就強行測它在非A的情況下返回一個undefined,則沒有太多價值。對這類情況,用UI行為測試主要條件即可,如果你實在覺得有重要的邏輯沒有被覆蓋,不妨回過頭來想想,是不是漏掉了某種輸入條件,例如特定的用戶鍵入或者特殊的API mock返回值。但是,當有過多的條件分支很難用業務場景去表述和模擬的時候,我們可能需要重新思考代碼的實現邏輯是否合理了。

當然,即使按上面這樣做,有時候還是會發現要覆蓋的條件組合太多,從行為流程上寫測試太復雜,這時就不得不做一定的妥協,為那些沒有獨立性的部分去單獨寫測試。如果這類測試不太好寫,可以參照剛才提到的SWR官方測試用到的技巧,把要測的函數或者是對象放置在一個臨時的UI組件下,以最小的成本做UI行為測試。

最后

總結一下上面談到的幾個原則:

(1) 從真實用戶的行為流程去測試,往往比測函數本身,能給你帶來更多的信心。

(2) 對于沒有獨立性和通用性的函數或對象,把它們視作實現的一部分,一般沒有必要為它們去寫單獨的測試。不要拘泥于對“單元測試”的字面理解,不要被形式上的規律所束縛。

(3) 不要把測試覆蓋率視為太過重要的指標,它的目的還是幫助提升代碼的穩定。有的代碼沒有覆蓋也沒關系,有的代碼值得你覆蓋好多遍。畢竟,我們不是為了寫測試而寫測試。

【本文是51CTO專欄作者“ThoughtWorks”的原創稿件,微信公眾號:思特沃克,轉載請聯系原作者】

戳這里,看該作者更多好文

 

責任編輯:趙寧寧 來源: 51CTO專欄
相關推薦

2011-05-24 09:30:26

Findbugs

2009-07-07 09:38:37

ServletQuer

2012-02-02 09:21:39

編程

2014-07-30 10:08:13

Python反模式

2024-07-26 10:28:51

2009-06-29 17:39:31

JSP設計模式

2024-02-28 08:38:07

Rust前端效率

2020-09-14 08:30:44

Kubernetes容器

2023-10-30 18:59:38

REST API開發

2017-04-12 11:46:46

前端瀏覽器渲染機制

2023-09-13 11:58:17

云原生反模式

2020-08-17 07:48:54

物聯網

2010-04-16 16:12:51

jdbc分頁

2011-06-14 14:27:43

灰盒測試

2009-07-07 16:39:40

JDK Observe

2021-01-11 05:37:54

倉儲模式接口

2020-05-07 17:30:49

開發iOS技術

2021-04-20 22:09:13

Python編程語言

2015-09-22 10:56:13

Java反模式

2015-10-10 11:23:17

Java常量反模式
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久精品com| 成人免费视频网站在线看 | 99久久婷婷国产精品综合 | 青青激情网| 欧美久久久久久久 | 亚洲精品久久久一区二区三区 | 精品一区二区三区av | 国产精品3区 | 国产精品久久九九 | 亚洲视频一区二区三区 | 男女羞羞免费视频 | 亚洲一区二区三区久久 | 日韩电影一区 | 一区二区三区亚洲 | 99热.com| 日韩综合在线 | 亚洲精品亚洲人成人网 | 国产精品久久久久久久久久久免费看 | 性高朝久久久久久久3小时 av一区二区三区四区 | 欧美 日韩 国产 成人 在线 | 国产精品久久久久久久岛一牛影视 | 亚洲精品毛片av | 欧美xxxx色视频在线观看免费 | 精品一区av | 成年无码av片在线 | 羞羞视频网 | 99精品99| www.久久久久久久久久久 | 国产精品一区二区久久久久 | 精品一区二区三区在线观看 | 日韩一二区 | 久久亚洲国产精品日日av夜夜 | 天天操天天干天天曰 | 国产亚洲欧美日韩精品一区二区三区 | 国产在线视频一区二区 | 国产你懂的在线观看 | 免费观看的av | 日本精品一区二区三区在线观看视频 | 欧美视频福利 | 久久久久国产一级毛片高清网站 | av先锋资源|