[TOC] # J_Vanilla JS 測試心路歷程 ## 前言 寫完專案進入空窗期,因為看到前輩的面試分享,內容有提到「單元測試」,且其實切版 t7.1 裡,也有提到要對功能做單元測試: > 就在這!! ![image](https://hackmd.io/_uploads/B1RqW7_Xxx.png) 所以趁現在有 to do list 這種小型專案,來寫寫看測試吧~ ## Vanilla JS Unit Test JS17 中,我們寫過了許多單元測試,即是將邏輯利用 function 獨立出來做測試,我可以理解 to do list 中有純邏輯的部份(例如:排序)。咦?結果就只找到排序是純邏輯,這樣只寫一個測試不合理啊,所以我去 Google 到了這篇神Q所寫的文章: [Unit Test | 香草 JS 的單元測試 feat. @testing-library/dom](https://medium.com/starbugs/unit-test-%E9%A6%99%E8%8D%89-js-%E7%9A%84%E5%96%AE%E5%85%83%E6%B8%AC%E8%A9%A6-feat-testing-library-dom-f8539137bec9) 稍微理解了,其實 DOM 也可以做測試,內文應該主要在講測試 function 時,如果遇到需要 DOM 的狀況,就補 DOM 給他,讓其不會報錯,就能專心測邏輯了~ 到這邊我想起了曾經與 Chris 聊過的測試話題,寫測試的目的,其實不只是要證明程式碼可以運行,主要是要展示 function 的極限跟使用方法。 Chris 也常常提到,測試要寫到什麼程度,就是取決於什麼情況會被客訴,在測試中寫到的所有狀況,都可以算是「正常情況」,也就是說,就算 function 出錯了,如果你在測試中有寫道,在某某情況 function 是會報「某某」錯的,而使用者也確實有這樣使用,那就屬於「預期內」的狀況,就不是「異常狀況」。 所以我也理解為,function 的「使用說明」,怎麼用這個 function 會吐出什麼內容;怎麼用 function 會出錯等等... 想完這些,就覺得測試也可以寫得非常冗長,因為我認為「畫面」也很有測試的必要,告訴使用者,哪個 function 是點擊某某元件觸發的,觸發後會如何調整 DOM,在畫面上會如何呈現才是預期的,又當資料來時,畫面有沒有長出對應的項目,且項目內的每個欄位中,有沒有填入應該項目的資料等等... 未免想太多了!裝上 jest 先跑一個試試看: ```javascript // initTabsSwitching.js export function initTabSwitching(liList) { liList.forEach((li) => li.addEventListener("click", function () { liList.forEach((li) => li.classList.remove("active")); this.classList.toggle("active"); }) ); } ``` 這段是在對指定 li list 中的`<li>`做事件綁定,當點擊某個`<li>`時,將該`<li>`的 class 加上 active ,其餘`<li>`的 active 都拿掉。 ```javascript= // initTabsSwitching.test.js import { initTabSwitching } from "../initTabsSwitching.js"; describe("li click 行為測試", () => { test("點擊第一個<li>,只有第一個<li>有 active", () => { //Arrange document.body.innerHTML = ` <ul> <li>A</li> <li>B</li> <li>C</li> </ul> `; const liList = document.querySelectorAll("li"); //Act initTabSwitching(liList); liList[0].click(); //Assert expect(liList[0].classList.contains("active")).toBe(true); expect(liList[1].classList.contains("active")).toBe(false); expect(liList[2].classList.contains("active")).toBe(false); }); } ``` 結果代誌大條了: ![image](https://hackmd.io/_uploads/r1WSAMT7gl.png) 大致是就是說 Jest 看不懂我寫的 import 語法 以往我都使用 ES module 來寫程式(import/export的方式),但 Jest 本身是使用 CommonJS 來寫,所以只認得 require/module.exports 寫法,所以解法一,就是將所有 ES module 寫法都改成 CommonJS 寫法,但我認為不太實際,現在是因為專案很小,而且都我自己寫的,要改可能工程不會太大,但如果今天是一整個團隊的案子,要改的部分可就不容小覷了,所以方法二,安裝 babel 來將 ES module 的不了字動轉譯成 CommonJS ## Babel 所以我們就照著官網來裝 babel: ![image](https://hackmd.io/_uploads/By6Ztzp7lg.png) ``` npm install @babel/preset-env --save-dev ``` 建立`babel.config.json`: ```json { "presets": ["@babel/preset-env"] } ``` 再跑一次試試看吧~ ![image](https://hackmd.io/_uploads/SyB-0G67ee.png) 成功跑了測試,但`document is not defined`... ## jest-envioronment-jsdom 表示在node環境中是沒有 DOM 的,於是去 Jest 搜尋了 DOM 的測試: [Jest-DOM Manipulation ](https://jestjs.io/docs/tutorial-jquery) 前面都在講用 jQuery 怎麼寫等等... 到最後看到這句關鍵,要裝`jest-environment-jsdom`來模擬 DOM 的操作~ ![image](https://hackmd.io/_uploads/SyvteXTXll.png) ``` npm install --save-dev jest-environment-jsdom ``` 然後在測試範例中看到這段: ![image](https://hackmd.io/_uploads/SyMMMm6meg.png) 所以我們就在`package.json`中加上`testEnvironment`: ```json { ... "scripts": { "test": "jest", "test-coverage": "jest --coverage", "watch": "sass --watch ./Jeremy/scss/main.scss ./Jeremy/css/main.css" }, "jest": { "testEnvironment": "jsdom" }, ... } ``` 終於成功啦! ![image](https://hackmd.io/_uploads/HyXxmXaXex.png) 接著就可以開始我們的 to do list 測試之旅了...
{"showTags":"false","title":"J_Vanilla JS 測試心路歷程","description":"寫完專案進入空窗期,因為看到前輩的面試分享,內容有提到「單元測試」,且其實切版t7.1裡,也有提到要對功能做單元測試,","contributors":"[{\"id\":\"ea951d67-eaab-46d0-b797-96b6bafbbfbc\",\"add\":3635,\"del\":140}]"}
Expand menu