iT邦幫忙

2026 iThome 鐵人賽

DAY 29
0
Software Development

程式設計沒有告訴你的事:30 天破解每一個 Why系列 第 29

Framework 組好了,但真的能用嗎?開始做完整整合測試

  • 分享至 

  • xImage
  •  

做到昨天,Mini Web Framework 的核心架構已經差不多成形了。

目前整體流程可以想成:

Browser

MiniWebServer

HttpRequest

Middleware Pipeline

Router

Handler

HttpResponse

Browser

一路做到這裡,很容易產生一種感覺:

功能都有了,那應該就完成了吧?

但其實還不能這麼快下結論。

因為:

可以跑一次

真的可以穩定使用

其實是兩回事。

例如:

/hello 可以成功

不代表 /products 一定成功。

成功的 Route 可以執行

不代表不存在的 Route 一定會正確回 404。

第一次 Request 正常

也不代表第二次、第三次 Request 還會正常。

Middleware 看起來有執行

也不代表每一次 Request 都真的按照正確順序經過。

所以今天不再新增新的 Framework 功能。

今天想做的是:

完整驗證前面建立的所有核心流程。

也就是:

Framework 組好了,但它真的能用嗎?

💭 我原本以為……

以前寫程式時,很容易把:

Build succeeded

或:

程式成功跑出一次結果

當成:

完成。

例如:

輸入 /hello

Browser 顯示 Hello!

就會覺得:

Routing 做好了。

但現在開始發現,Framework 是一個會一直處理不同 Request 的系統。

所以只測試一種 Happy Path 根本不夠。

至少要問:

正常 Request 可以嗎?

不同 Route 可以嗎?

錯誤 Route 可以嗎?

連續 Request 可以嗎?

Middleware 每次都會執行嗎?

Response Status 正確嗎?

如果某一層出錯怎麼辦?

這些問題才比較接近:

這個 Framework 到底能不能真正運作。

什麼是整合測試?

前面我們很多實驗都是測單一概念。

例如:

Day12

測 Request Parsing

Day13

測 Routing

Day14

測 Response

Day15

測 HttpResponse

這些都比較像:

把某一個功能單獨拿出來看。

但今天要做的是:

把所有東西接在一起後,再從最外面測一次。

例如:

Browser

Request

Middleware

Router

Handler

Response

Browser

如果這整條流程可以正常跑通,就代表各個元件之間至少能一起合作。

這種「多個元件一起驗證」的思路,就是今天最重要的地方。

第一個要測什麼?

最基本的當然還是:

/hello

例如:

GET /hello HTTP/1.1

預期流程:

Request 進入 Server

HttpRequest 解析成功

Middleware 執行

Router 找到 /hello

Hello Handler

200 OK

Browser 顯示 Hello!

這個測試雖然簡單,但它其實一次驗證了很多東西。

包括:

TCP

Request Parsing

Routing

Handler

Response

Middleware

只要其中一層有問題,最後都可能看不到 Hello。

第二個測試:/products

接著不能只測一條 Route。

還要測:

/products

因為如果:

/hello 可以

/products 不行

就可能代表 Router 註冊或匹配其實還有問題。

所以第二個測試應該確認:

GET /products HTTP/1.1

Router

Products Handler

200 OK

Products Page

這可以證明:

Framework 不是只對某一條 Route 寫死。

而是真的可以處理不同 Route。

第三個測試:不存在的 Route

這個測試非常重要。

例如:

/abc

Route Table 裡沒有。

Framework 不應該:

Crash

卡住

或完全不回應。

應該清楚地:

找不到 Route

404 Not Found

回給 Browser

所以:

GET /abc HTTP/1.1

Router Match Failed

404 HttpResponse

Browser 顯示 404 Not Found

如果這個測試成功,表示:

Framework 已經不只會處理成功情況。

也開始可以處理最基本的錯誤情況。

200 和 404 都要確認

不能只看 Browser Body。

因為:

Hello!

和:

404 Not Found

只是 Body。

真正 HTTP Response 還包含:

Status Code。

所以理想上也應該確認:

/hello

200 OK

/products

200 OK

/abc

404 Not Found

這樣才能知道:

Framework 不只是顯示不同文字。

而是真的建立了不同的 HTTP Response。

Middleware 要怎麼測?

Day28 加入 Middleware 後,如果只是看到:

有印一行 Logging

其實還不夠。

更重要的是確認執行順序。

例如預期:

Request 開始:GET /hello

Handler

Request 完成:GET /hello

這樣才能證明:

Middleware 真的是:

Before

next

After

而不是單純在某個地方:

Console.WriteLine()

所以 Console 的輸出順序本身就可以成為一種測試。

例如:

[Logging] Request Start: GET /hello

找到 Route

執行 Hello Handler

已回傳 200 OK

[Logging] Request End: GET /hello

如果這個順序正確,就可以更有信心:

Pipeline 真的有被組起來。

連續 Request 為什麼要測?

這是我們自己寫 Server 時特別重要的一點。

因為 Framework 不是只服務一個 Request 就關掉。

它需要:

Request 1

處理完成

Request 2

繼續處理

Request 3

繼續處理

例如可以依序測:

/hello

/products

/abc

再回到:

/hello

如果 Server 每次都可以繼續:

正在等待 Browser…

就代表最基本的 Server Loop 還正常。

如果第一個 Request 成功後程式就結束,

那就不是一個能持續服務的 Web Server。

之前學過的 while(true) 在這裡又重新變得重要。

Browser 為什麼可能送出不只一次 Request?

前面實驗時已經看過,有時候 Browser 可能出現多個連線或額外 Request。

所以測試時不能看到 Console 多出一行就立刻認為:

Framework 壞了。

Browser 本身可能有:

重新連線

額外資源請求

其他行為。

更重要的是觀察:

每一份被 Framework 收到的 Request,有沒有被正常處理。

這也是自己手刻 Server 和使用成熟 Framework 最大的差異之一。

以前這些細節幾乎都被藏起來了。

Request Parsing 還有風險嗎?

有。

目前我們為了學習,很多地方都使用非常簡化的 Parsing。

例如:

Split

一次 NetworkStream.Read()

固定 buffer

這些都不是真正 Production HTTP Server 應該使用的完整處理方式。

尤其 Day19 已經知道:

TCP 是 byte stream。

一次 Read 不保證完整取得整個 Request。

所以 Day29 測試成功,代表的是:

目前這個學習環境下的 Mini Framework 可以運作。

不是代表:

我們已經做出完整符合所有 HTTP 情況的 Production Server。

這個界線非常重要。

因為這次專案的目標是:

理解 Framework。

不是取代 Kestrel。

測試時發現問題代表失敗嗎?

不是。

反而相反。

今天的目的就是:

把問題找出來。

例如可能發現:

/hello 正常

/products 正常

/abc 卡住

那就表示:

404 流程沒有接完整。

或者:

第一次 Request 有 Logging

第二次沒有

那表示:

Middleware Pipeline 可能只建立或執行一次。

再例如:

Response Body 正常

但 Status Code 不對

那就表示:

Response 建立邏輯有問題。

所以 Testing 的價值就是:

讓「我以為它可以」

變成:

「我有證據知道它在哪些情況可以」。

這兩句話差非常多。

錯誤處理要做到多完整?

最後兩天時間有限。

所以 Day29 不需要突然做一套完整 Error Handling Framework。

但至少可以想清楚三種結果:

正常

200

Route 不存在

404

Framework 發生未預期錯誤

最好不要直接整個 Server Crash

如果 Middleware Pipeline 已經有空間,也可以想像:

Exception Middleware

try

next()

catch

500

即使最後成品沒有把所有細節做完,

至少架構上已經知道:

500 應該放在哪一層處理。

這比每個 Handler 自己 try/catch 更符合 Framework 設計。

要測什麼才算 Day29 完成?

對這個 Mini Web Framework 來說,可以建立一份最小 Checklist。

第一:

Server 可以正常啟動。

第二:

/hello 回 200 + Hello!

第三:

/products 回 200 + Products Page

第四:

不存在 Route 回 404。

第五:

連續 Request 不會讓 Server 結束。

第六:

Logging Middleware 每次 Request 都有執行。

第七:

Request → Router → Handler → Response 的流程可以從 Console 觀察。

如果這七項都通過,

其實就已經足以證明:

Mini Web Framework 的核心真的串起來了。

📚 官方怎麼說?

在正式軟體開發中,Testing 不只是確認某一個 Method 是否能執行。

當多個 Component 需要合作時,也需要確認它們之間的整合是否符合預期。

對 Web Application 而言,Request Processing 往往跨越:

Middleware

Routing

Endpoint

Response

等多個元件。

所以只驗證單一 Class 並不足以代表整個 Request Flow 正常。

而我們今天做的雖然只是手動的最小整合測試,

核心想法也是:

從 Request 進入,到 Response 離開,

整條流程一起驗證。

🧠 今天的認知更新

以前的我:

跑出一次 Hello

成功

現在的我:

不同 Route

不同 Handler

正確 Response

錯誤 Route

404

連續 Request

Server 繼續執行

Middleware

每次都按照順序執行

全部通過後,

才能比較有把握說:

Framework 的核心流程真的可以工作。

🔍 今日最大的發現

今天最大的發現是:

「可以執行」和「可以被信任」之間,中間還隔著 Testing。

前面一直在寫:

Framework 應該怎麼做。

今天開始反過來問:

我怎麼知道它真的有做到?

例如:

Router 真的會找到不同 Handler 嗎?

Middleware 真的包住 Handler 嗎?

404 真的會回出去嗎?

第二個 Request 真的還能進來嗎?

這些都不能只靠:

我覺得程式應該會這樣跑。

而要透過實際測試確認。
Framework 組裝完成後,不能只看它能不能啟動。

還需要從外部真的送出不同 Request,

確認 Request Parsing、Middleware、Routing、Handler、Response、404 等元件可以一起正確合作。

只有整條 Request / Response Flow 都經過驗證,才比較能確認這個成品真的成立。

🛠 與 Mini Web Framework 的關聯

Day26:

把 Framework 拆成不同元件。

Day27:

把 Router、Handler、Response 接起來。

Day28:

加入 Middleware Pipeline。

Day29:

不再新增大量功能。

而是把所有東西一起測一次。

整個驗證流程可以是:

啟動 Framework

GET /hello

200 Hello!

GET /products

200 Products Page

GET /abc

404 Not Found

再送 /hello

仍然成功

同時 Console:

Middleware Before

Routing

Handler

Response

Middleware After

如果全部符合預期,

那這 29 天從零開始追的所有 Why,

就真的開始變成一個可以展示的成果。

今天的實作目標

Day29 真正實作時,重點不是再新增 Class。

而是整理一份測試紀錄。

可以實際測:

/hello

/products

/abc

連續多次 Request

Logging Middleware

並把 Console 結果和 Browser 畫面保留下來。

如果中間遇到 Bug,

就記錄:

問題是什麼

為什麼發生

最後怎麼修

其實這種內容非常適合放在 Day29 文章裡。

因為真實專案的最後階段本來就不會永遠一次成功。

Debug 本身就是開發的一部分。

結尾

一路做到 Day29,今天第一次沒有急著問:

下一個功能要加什麼?

而是回頭看:

前面做的東西到底能不能一起工作?

這讓我發現,做成品和做練習題很不一樣。

單獨做 Routing 時,只需要確認:

Path 能不能找到 Handler。

單獨做 Response 時,只需要確認:

Browser 能不能看到 Hello。

但當它們真正變成 Framework,

所有元件都必須在同一個 Request 裡合作。

Browser

Server

Request

Middleware

Router

Handler

Response

Browser

只要任何一層出問題,整條流程就可能失敗。

所以今天最大的工作不是增加功能。

而是建立信心:

我不是只是把很多概念寫在文章裡。

這些概念真的可以被組成一條可以執行的 Framework Pipeline。

而明天,就是最後一天。

❓最後一個 Why

Day1 的時候,我問的是:

為什麼學了那麼多程式,遇到真正的問題時,我還是不知道程式到底怎麼運作?

29 天後,我已經一路從:

C#

Compiler

IL

JIT

CPU

走到:

TCP

HTTP

Routing

Request

Response

Reflection

Binding

Middleware

最後甚至自己組出一個 Mini Web Framework。

所以最後一天,不應該再繼續新增新功能。

真正該問的是:

這 30 天,我到底理解了什麼?

以及:

我真的做出了什麼?


上一篇
把 Middleware 接進來:我的 Framework 終於有 Request Pipeline 了
下一篇
從「我只會用 Framework」到「我知道 Framework 為什麼存在」:30 天最終成果
系列文
程式設計沒有告訴你的事:30 天破解每一個 Why30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言