# 2019 JavaScript Testing Note
Material: [Testing JavaScript with Kent C. Dodds](https://testingjavascript.com/)
## Summary
選擇此教材的依據
- open source 社群口碑(EggHead family、React family)
JS 測試聖杯的用處
- 第一層 static analysis 用來避免 type error 這類的低級錯誤
- 第二層 unit test 用來避免函式回傳結果算錯
- 第三層 integration test 用來避免 dom 被 render 錯
- 第四層 end to end test 用來節省 QA 的工時
實務界見解
- 第一層有人會用 TypeScript 解決,不過 TS 寫起來真的超煩的喇
- 第二層的特性是好寫、effort 小但效益大,用過都說讚(?
- 第三層其實常常被跳過,反正頭尾有對,中間就 www
- 第四層是最多人真的做的,不過只做這層就變成傳說中的蕈狀雲 XD
研究結論
- 第一層:教材用 Flow,但教材的作者最近從 Flow 跳槽到 TS 了,所以我決定先用 create-react-app 內建的陽春工具 propTypes,一邊觀望後續發展 😆
- 第二層:如果有容易算錯結果的 pure functions 就還蠻需要的,但我這邊好像沒什麼這種 function ... 😓
- 第三層:課程海報鼓勵多數測試寫 integration,可能因為現代的 single page app 裡面吃重的功能通常都是多個 unit 連動的結果。我們的 wizard 好像蠻需要這個的 🤔
- 第四層:不管有沒有要寫都會先導入 Cypress,當開發工具用 😂
詳細筆記 https://hackmd.io/EBZQe4zrQgeXLDJbGEcYKw
## Chapter 1 Fundamentals of Testing in JavaScript
https://testingjavascript.com/courses/fundamentals-of-testing-in-javascript
看完可以知道
- 測試工具幹嘛用的、語法為什麼會設計成那樣,以 Jest 為例
個人收穫
- pure functions 適合 unit test(結果不是這意思,只是適合拿來 demo 這一章 XD)
- state / event 相關的 functions 可能適合別的,後面應該會講到吧(就是 react-testing-library 的 fireEvent 啦)
## Chapter 2 Static Analysis Testing JavaScript Applications
https://testingjavascript.com/courses/static-analysis-testing-javascript-applications
看完可以知道
- 怎麼在 node js 開發環境設定 linter,以 ESLint 為例
- 怎麼在 node js 開發環境設定 formatter 並且讓它跟 linter 相容,以 Prettier 為例
- 怎麼在 node js 開發環境設定 type checking tools 並且讓它跟 linter 相容,以 Flow 為例
- 怎麼在 node js 開發環境設定 pre-commit git hook 以預防沒通過 linter / formatter / type checking 的 code 被 commit 進去,以 Husky 為例
- 怎麼在 node js 開發環境讓 pre-commit git hook 只處理有變更的檔案以節省時間,使用 lint-staged
個人收穫
- ESLint 是 linter,Standard 是 eslint 的設定套餐附上一點點 formatter 功能,Prettier 則是專門的 formatter,Prettier 跟 Standard 可以同時採用,像這樣 https://www.npmjs.com/package/prettier-standard
與手上專案的關係
- linter 已經由 Create React App 設定好了
- 已經有 Standard 提供的基本 formatting 功能,更專門的 formatter 就暫時不理他
- 至於 type checking,React 內建 PropTypes 但大家(?)說 Flow 比較完整跟方便也不會拖慢 compile 速度,可能到時候實際試一下比較看看手感再來選。另一個解法是改寫 TypeScript 但據說寫起來超麻煩而且也不符合目前的進程,所以不考慮 XD
- 至於 pre-commit git hook 相關的東西,也是到時候看看,影響不大 XD
## Chapter 3 JavaScript Mocking Fundamentals
https://testingjavascript.com/courses/javascript-mocking-fundamentals
看完可以知道
- 測試工具的 mock 功能是幹嘛用的、語法為什麼會設計成那樣,以 Jest 為例
個人收穫
- 嗯就知道 mock 功能的運作原理這樣...
## Chapter 4 Configure Jest for Testing JavaScript Applications
https://testingjavascript.com/courses/configure-jest-for-testing-javascript-applications
看完可以知道
- 怎麼在 node js 開發環境設定設定測試工具的各種功能,以 Jest 為例
個人收穫
- 專案 source code 是透過 Webpack 跑在 node 上,但 Jest 是直接跑在 node 上,因此許多透過 Webpack 設定才會生效的東西,在跑 Jest 時要另外處理,例如 es6 module、css loader、css module、dynamic import
- Jest 可以設定成在 node 上面跑,也可以設定成在 jsdom 製造的假 browser 上面跑,後者才會有 window 物件可以呼叫,是預設值,但效能會比較低,用不到就關掉ㄅ
- 如果遇到改規格的情況,除了改程式本人以外,assertion 用的標準答案也要跟著改,Jest 知道手工改標準答案很煩,所以做了 snapshot 這功能讓我們可以把執行結果 serialize 成標準答案的檔案,這個檔案是要跟程式本人一起 commit 進去的,然後 Jest 跑測試時會依照跑出來的結果是否跟標準答案一樣,來判斷 assertion 有沒有通過
- 每個測試檔案都會用到的東西可以直接寫到 Jest 的設定檔裡面
- 程式有用到 dynamic import 的話 Jest 會測到還沒載入時的狀態,如果是要測載入後的狀態,要另外設定
- 程式有用到 context api 工具如 React Router 之類的話,那測試也要把 providers 寫進去,不然就不會過。但每支測試都要摻 provider 很煩,這時候可以把 providers 寫到自訂的 render method 裡面
- debug Jest 的時候如果狀況比較複雜,可以透過 node 的工具偷用 chrome 的 developer tool,有精美 GUI 也認得 debugger,就不用一直到處 console.log 了
- Jest 可以直接出 coverage report 到 coverage 資料夾裡面,是個小網頁~但預設會連測試的 js 都算進去,而且只算測試檔案有召喚的程式檔,要橋一下設定
- 可以指定 coverage 低於某個百分比測試就不通過 XD (完全不想用這功能欸哈哈)
- 可以把 coverage report 接到第三方去做進一步的視覺化(甚至投影在辦公室對大家施壓 XD)在 CI 裡面設定就可以了ㄛ(沒 CI 的專案表示...)
- Jest 也有 watch mode,你隨時存檔他隨時測,而且會比對上個 git commit 只測有更動過的檔案。watch mode 還有一堆有的沒的互動功能,可以指定要測哪,debug 的時候蠻實用的
- 有 CI 的話一般會想在 CI 時出 coverage report,在 local 時打開 watch mode,有個 lib 可以幫你偵測環境然後自動跑適當的 test 指令
- watch mode 的 regex 模式還可以另外裝個小 plugin 讓你預覽 regex match 的結果
- 可以把不同環境(client / server)的專案混成撒尿牛丸一起跑測試,同時還可以指定哪個專案要 watch 哪個專案不用 watch
與手上專案的關係
- 這章的一堆設定是使用自訂的 webpack 環境要做的,不過我們用 Create React App,裡面很多設定應該都預先做好了 :3
- 嗯不過如果想改設定的話,就要 eject 才行了,我現階段不想 eject 就是了 XD
## Chapter 5 Test React Components with Jest and react-testing-library
看完可以知道
- 怎麼用測試工具確定 React render 出來的 dom 裡面的東西有該有的 attribute 或文字內容,以 Jest 為例
- react-testing-libarary 為了幫你做好 dom testing 而設計的一堆懶人功能
個人收穫
- 意外(?)發現 react 的 dependency injection 蠻好用的,就是把一些可能在別的環境(如測試環境)要抽換的東西設定成 defaultProps
與手上專案的關係
- 替 dom element 加上 data-testid 屬性吧,integration test 跟 e2e test 都用得到
## Chapter 6 Install, Configure, and Script Cypress for JavaScript Web Applications
看完可以知道
- 2018 年開始爆紅的 JS focused end to end testing tool 怎麼設定跟使用
個人收穫
- Cypress 亮點:不用網路本機直接跑,直接跟 JS 專案無痛接軌,平常用的 debugging tools 都可以直接用
- 所以甚至開發時就直接用 cypress 裡面的 chrome 就好了不用另外從 os 開 chrome,需要 state change 時就叫 cypress 幫你按就好 XD(CDD!)
- 嗯還可以 mock server response... (問題來了,這樣我還要用 json server 嗎?答案:搭配著同時用 [Add GUI to your E2E API tests](https://www.cypress.io/blog/2017/11/07/add-gui-to-your-e2e-api-tests/) )
其他參考資料
- [Cypress vs Selenium WebDriver: Better, or just different?](https://applitools.com/blog/cypress-vs-selenium-webdriver-better-or-just-different)
- Selenium was built as a multi-language, cross-browser tool, that fits multiple purposes, not just testing.
- Cypress, on the other hand, was built for one thing, and one thing only, executing frontend developers tests fast and consistently.
- Cypress seems so limited: it supports just one language (JavaScript), one framework (Mocha), and one browser (Chrome). But these limitations are mostly not a problem for frontend developers, and enable Cypress to give frontend developers the advantages that they do need: speed and consistency.
- Selenium WebDriver does not have these limitations. It cannot have these limitations because it is a general purpose tools for multiple target audiences.
- [Selenium vs. Cypress: Is WebDriver on Its Way Out?](https://crossbrowsertesting.com/blog/test-automation/selenium-vs-cypress/)
- Selenium is a library but requires a unit testing framework or a runner plus an assertions library to build out its capabilities.
- Cypress provides a robust, complete framework for running automated tests but takes some of the freedom out of Selenium by confining the user to specific frameworks and languages.
- [Cypress vs. Selenium, is this the end of an era?](https://automationrhapsody.com/cypress-vs-selenium-end-era/) (內有超完整規格比較)
- I truly believe it is the end of Developers don’t test era. Selenium may not be their favorite tool, but Cypress is made from developers for developers. It is easy to work with and provides features to speed up test writing. If you try the tool and do not like it, at least try to introduce it to developers in your company.
- I have used Selenium way too much in order to dislike it. Tests with it are slow and flaky. I really hope there is something better out there. On the other hand, I have used Cypress way too little to like it very much and think this is the tool. In any way do try Cypress. If you do not like it, then definitely introduce it to your developers.
- [Why you should switch to Cypress for modern web testing?](https://medium.com/@shivambharadwaj/https-medium-com-shivambharadwaj-why-you-should-switch-to-cypress-for-modern-web-testing-5d3739a19e6)
- Challenges in modern web testing
- Dealing with XHR calls and web services
- Short deployment sprints, and major time involved in testing
- Security of data
- Very expensive to maintain due to lack of infrastructure for testing
- Dynamic behavior of application due to modern development frameworks
- Many more yet to come in future….
- These are some problems associated with selenium. Selenium has been a major player in E2E web application testing for a decade now. But modern web is different today, in order to overcome these shortcomings of selenium cypress comes in picture here.
與手上專案的關係
- 採用確定 XD