---
# System prepended metadata

title: 單元測試 範例 `word prediction`
tags: [unit-test]

---

# 單元測試 範例 `word prediction`

###### tags: `unit-test`

**WIP**此專案還沒做整合測試。

透過 馬卡夫鏈 推斷使用者接下來要輸入的字，
此為 `NLP` 的入門演算法。

## 配置跟設定

會使用到的套件：
- `typescript`
- `jest`
- `esbuild`
- `esbuild-jest`
- `fast-check`
- `msw`

只寫必要的 setting， 其他多餘的不寫

`jest.config.js` 
```js
module.exports = {
  transform: {
    "^.+\\.tsx?$": "esbuild-jest",
  },
};
```

`tsconfig.json`
```json
{
  "extends": "@tsconfig/node16/tsconfig.json",
  "include": ["src/**/*", "packages/**/*"],
  "compilerOptions": {
    "baseUrl": "src",
    "paths": {
      "discord/types": ["../packages/types"]
    }
  }
}
```

## 分析

此程式主要被拆做 4 個 函式，可以參考 `main.ts` 的說明
- `src/read_text_from.ts` => `src/__tests__/read_text_from.ts`
- `src/tokenize.ts` => `src/__tests__/tokenize.ts`
- `src/to_n_grams.ts` => `src/__tests__/to_n_grams.ts`
- `src/lookup.ts` => `src/__tests__/lookup.ts`

### `read_text_from`

因為是對外部系統做讀寫，此函式是有 `side effect` 的。

測試主要分做兩個部分：
- 本地端讀寫
  本地端讀寫是透過 `node` 的 `fs/promise` 模組。
  透過 `jest.spyOn` 跟 `mockImplementation` 我們可以 mock 掉 `fs.readFile`。

  測試邏輯是，
  預期測試拋入的路徑只有 `exist_local_path` 會通過測試，
  當拋入路徑不符合會拋出 `SystemError ENOENT`，
  根據 https://man7.org/linux/man-pages/man3/errno.3.html

  詳參：
  https://github.com/kayac-chang/word-prediction/blob/main/src/__tests__/read_text_from.test.ts
  Line 21 ~ 33 `BeforeEach`
  Line 35 ~ 49 `describe("read from disk")`

- 遠端讀寫
   使用 `msw` 來模擬回應 API 請求，沒什麼特別的，略過。
   
  詳參：
  https://github.com/kayac-chang/word-prediction/blob/main/src/__tests__/read_text_from.test.ts
  Line 9 ~ 14 `setupServer`
  Line 17 ~ 19 `server.listen` `server.resetHandlers` `server.close`
  Line 51 ~ 66 `describe("read from remote")`

### `tokenize`

此函式將 句子分解成 單字，透過空白分割。
任何標點符號都應被保留，但空白必須被移除。

詳參：
https://github.com/kayac-chang/word-prediction/blob/main/src/__tests__/tokenize.test.ts

### `to_n_grams`

此函式為 _Higher Order Function_，故先行測試 第一層回傳是否符合 範疇論，
透過驗證 回傳 是否是 函式。

詳參：
https://github.com/kayac-chang/word-prediction/blob/main/src/__tests__/to_n_grams.test.ts
Line 5 ~ 12

測試函式行為，此處只測試 3 節 的情況。

詳參：
https://github.com/kayac-chang/word-prediction/blob/main/src/__tests__/to_n_grams.test.ts
Line 14 ~ 32

### `lookup`

此函式為 _Higher Order Function_，故先行測試 第一層回傳是否符合 範疇論，
透過驗證 回傳 是否是 函式。

詳參：
https://github.com/kayac-chang/word-prediction/blob/main/src/__tests__/lookup.test.ts
Line 5 ~ 7

測試函式行為，此處只測試一個字典。

詳參：
https://github.com/kayac-chang/word-prediction/blob/main/src/__tests__/lookup.test.ts
Line 9 ~ 26

https://github.com/kayac-chang/word-prediction