# Day 4：TDD-Coverage；強制轉型；變數作用域

By [雞蛋糕的前端修煉屋](https://paragraph.com/@gcake) · 2025-11-26

jacascript, ecmascript, tdd

---

Coverage 覆蓋率
------------

> 「我寫的測試條件夠多了嗎？有每個判斷條件都跑嗎？極端情境有考慮到嗎？」

* * *

### 參數化測試

列舉同一個 function 多組不同輸入輸出一次測試的方法 實際寫的時候感覺很像窮舉法，但又不確定該寫幾組比較適當 所以開始思考評估測試程式碼的方法

* * *

Coverage 確認測試程式碼包含功能程式碼所有可能情境的程度

安裝：`pnpm i -D @vitest/coverage-v8` （預設值）

遇到相依 Vitest 版本不對齊的提示，強制升版到提示版本號：`pnpm up vitest@4.0.13 -D`

執行：`pnpm vitest run --coverage`

產生報表：

![](https://storage.googleapis.com/papyrus_images/7f4f107e52f48368d8276c1980d57aadaaba33218cbfbd346182eef10afc4655.png)

顯示 q1.js 的第 8,21 行在測試中沒有踩到

  

*   行沒被執行 → 代表「沒有任何一組輸入」讓執行流程走到那一行。
    
*   Branch 沒滿 → 至少有一個 if / else if / else / case / default 的某個出口沒被走過。例：只有測「valid input」，沒有測「邊界值 / 錯誤 input」，那錯誤處理分支就不會被覆蓋。
    

可以回頭檢視調整測試程式碼(q1.test.js)和功能程式碼(q1.js)：

1.  確認 q1.js 執行邏輯
    
2.  根據執行邏輯反推 q1.test.js 要補的測試條件
    
3.  補完後再次執行 `pnpm vitest run --coverage`確認，以上流程反覆進行
    

修改完確認測試覆蓋率 100%

![](https://storage.googleapis.com/papyrus_images/c429fbf8da83e812c55e54ffe6940406ed4928949b43821dde9563b210795cc0.png)

### 目前對 TDD + Coverage 的理解

*   在 TDD 流程中，檔案大致分工可以是：
    
    *   `app.test.js`：先寫測試，描述預期行為（紅燈）。
        
    *   `app.js`：再寫功能邏輯，讓測試通過（綠燈）。
        
    *   `main.js`：最後由主程式負責把 UI / 事件 / API 等互動，串接到 `app.js` 的功能邏輯。
        
*   TDD 的核心循環：
    
    *   先寫測試（紅燈）。單元測試是針對每個單一功能程式 function 撰寫測試。
        
    *   寫最小實作讓測試通過（綠燈）。
        
    *   在測試保護下重構程式碼（重構）。
        
*   Coverage 在這個流程中的角色：
    
    *   coverage 用來檢查「哪些程式碼路徑在測試中被執行過」，例如行（Lines）、敘述（Statements）、分支（Branches）、函式（Functions）。
        
    *   透過 coverage 報告可以找出「完全沒被任何測試踩到的邏輯路徑」，幫助判斷目前的測試案例是否還不夠完整，需要補哪些情境（例如錯誤輸入、邊界值、不同布林組合）。
        
    *   coverage 數字高代表「程式有被跑到」，**但不代表行為一定正確**；測試本身的斷言內容仍然可能寫錯或漏寫，所以 coverage 是輔助指標，不是品質保證書。
        

**補充文件**：

*   [Coverage | Guide - Vitest](https://vitest.dev/guide/coverage)
    
*   [Testing coverage | Config - Vitest](https://vitest.dev/config/coverage)
    
*   [Getting Started | Guide - Vitest](https://vitest.dev/guide/)
    
*   [Four common types of code coverage - web.dev](https://web.dev/articles/ta-code-coverage)
    
*   [程式碼覆蓋率（Code Coverage） - iT 邦幫忙](https://ithelp.ithome.com.tw/articles/10309187)
    
*   [Explain the concept of code coverage and how it can be used to assess test quality](https://www.greatfrontend.com/questions/quiz/explain-the-concept-of-code-coverage-and-how-it-can-be-used-to-assess-test-quality)
    
*   [Code Coverage vs. Test Coverage: What's the Difference?](https://blog.codacy.com/code-coverage-vs-test-coverage)
    
*   [Is 70%, 80%, 90%, or 100% Code Coverage Good Enough?](https://www.qt.io/quality-assurance/blog/is-70-80-90-or-100-code-coverage-good-enough)
    
*   [Red, Green, Refactor - Codecademy](https://www.codecademy.com/article/tdd-red-green-refactor)
    
*   [Test Driven Development - Martin Fowler](https://martinfowler.com/bliki/TestDrivenDevelopment.html)
    

#### 進階：突變測試 stryker mutator

一種用抽換功能程式碼邏輯以驗證與改善測試程式碼的方法

已安裝 pnpm 套件，留待之後再練習

[**官方文件**](https://stryker-mutator.io/docs/stryker-js/getting-started/)

ToBoolean 轉型學習記錄
----------------

今日閱讀：

*   《008 天重新認識 JavaScript！》第二天
    
*   《JavaScript 概念三明治》PART 1 基本語法與概念說明
    

### 先記住：falsy 值只有這些

在 JavaScript 裡，ToBoolean 會轉成 `false` 的值（稱為 falsy）只有以下幾種：

*   `undefined`
    
*   `null`
    
*   `false`（布林本身）
    
*   數字：`+0`、`-0`、`NaN`
    
*   空字串：`""` 或 `''`
    

除此之外的所有值，都會被 ToBoolean 轉成 `true`（稱為 truthy），包括非空字串、物件、陣列、函式、非零數字等等。

* * *

### `!!` 的轉型步驟（以練習題為例）

題目：

`!!false == !!true`

`!!false === !!true`

兩邊型別一樣（都是 boolean），所以這裡 == 和 === 的結果相同，而且實際比較結果都是 false，因為 false 不等於 true。

* * *

### 關鍵觀念整理

*   ToBoolean 規則：只要記住「那幾個 falsy」，其他全部都是 truthy。
    
*   `!!value` 的用途：把任何值強制轉成真正的 `boolean`，並保留原本的 truthy / falsy 含義。
    
*   字串陷阱：不管內容是 `"false"`、`"0"`、`"no"`，只要不是空字串，都會被當成 truthy，因此 `!!"false"`、`!!"0"` 都是 `true`。
    
*   當兩邊都已經是 `boolean` 時，`==` 和 `===` 行為一樣，但實務與風格上仍建議統一使用 `===` 以避免混淆。
    

### 其他強制轉型的寫法

*   轉型成字串：String(5), 5+""
    
*   轉型成數值：Number("5"), +"5"（一元運算子）
    
*   轉型成布林：Boolean(5), !!5
    

#### 物件強制轉型方法

*   轉型成字串：obj.toString(), String(obj)
    
*   轉型成數值：obj.valueOf(), valueOf(obj)/ Number(obj)
    

變數作用域與全域汙染
----------

把 function 使用的變數移到 function scope 宣告

---

*Originally published on [雞蛋糕的前端修煉屋](https://paragraph.com/@gcake/day-4)*
