<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Testing 知識卡片 on Tarragon</title><link>https://tarrragon.github.io/blog/testing/knowledge-cards/</link><description>Recent content in Testing 知識卡片 on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Fri, 19 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/testing/knowledge-cards/index.xml" rel="self" type="application/rss+xml"/><item><title>Protocol Integration Test</title><link>https://tarrragon.github.io/blog/testing/knowledge-cards/protocol-integration-test/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/testing/knowledge-cards/protocol-integration-test/</guid><description>&lt;p>Protocol integration test 的核心概念是「對真實服務實例驗證協議層行為」。它跳過 mock，直接連線到真實的外部服務，觀察連線握手、認證流程、資料編碼和回應格式是否符合協議規格。和 &lt;a href="https://tarrragon.github.io/blog/testing/knowledge-cards/mock-masking/" data-link-title="Mock 遮蔽" data-link-desc="mock 模擬 API 層但不模擬協議層，造成的結構性驗證盲區">mock 遮蔽&lt;/a>互補 — mock 遮蔽的盲區正是 protocol integration test 的驗證範圍。可先對照&lt;a href="https://tarrragon.github.io/blog/testing/knowledge-cards/nominal-integration-test/" data-link-title="名義 Integration Test" data-link-desc="名稱含 integration 但核心依賴全用 fake 的 test，驗證內部狀態機而非真實服務互動">名義 integration test&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Protocol integration test 位在 unit test 和 E2E test 之間。Unit test 用 mock 驗證程式碼邏輯，E2E test 經過 UI 驗證完整流程，protocol integration test 用程式碼直接呼叫 client 端連線函式、對真實服務執行操作。它填補「程式碼邏輯正確但協議互動錯誤」這個 mock 結構性無法覆蓋的空隙。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 protocol integration test 的訊號是：API 簽名用寬泛型別（&lt;code>dynamic&lt;/code>、&lt;code>Object&lt;/code>、&lt;code>Any&lt;/code>）隱藏了協議層的行為分支、mock 跳過了業務關鍵步驟（認證、握手）、或外部服務對錯誤輸入靜默忽略。WebSocket 的 text/binary frame 差異、gRPC 的 streaming deadline、MQTT 的 QoS level 都是典型場景。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Protocol integration test 要決定服務 fixture 的管理方式（Process.start / Docker / testcontainers）、健康檢查策略（port 可達 / HTTP health / 業務操作成功）、和狀態隔離方式（每 test 重啟 / 重設狀態 / 獨立 namespace）。成本判斷依據服務啟動成本和協議複雜度兩個維度。&lt;/p></description><content:encoded><![CDATA[<p>Protocol integration test 的核心概念是「對真實服務實例驗證協議層行為」。它跳過 mock，直接連線到真實的外部服務，觀察連線握手、認證流程、資料編碼和回應格式是否符合協議規格。和 <a href="/blog/testing/knowledge-cards/mock-masking/" data-link-title="Mock 遮蔽" data-link-desc="mock 模擬 API 層但不模擬協議層，造成的結構性驗證盲區">mock 遮蔽</a>互補 — mock 遮蔽的盲區正是 protocol integration test 的驗證範圍。可先對照<a href="/blog/testing/knowledge-cards/nominal-integration-test/" data-link-title="名義 Integration Test" data-link-desc="名稱含 integration 但核心依賴全用 fake 的 test，驗證內部狀態機而非真實服務互動">名義 integration test</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Protocol integration test 位在 unit test 和 E2E test 之間。Unit test 用 mock 驗證程式碼邏輯，E2E test 經過 UI 驗證完整流程，protocol integration test 用程式碼直接呼叫 client 端連線函式、對真實服務執行操作。它填補「程式碼邏輯正確但協議互動錯誤」這個 mock 結構性無法覆蓋的空隙。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 protocol integration test 的訊號是：API 簽名用寬泛型別（<code>dynamic</code>、<code>Object</code>、<code>Any</code>）隱藏了協議層的行為分支、mock 跳過了業務關鍵步驟（認證、握手）、或外部服務對錯誤輸入靜默忽略。WebSocket 的 text/binary frame 差異、gRPC 的 streaming deadline、MQTT 的 QoS level 都是典型場景。</p>
<h2 id="設計責任">設計責任</h2>
<p>Protocol integration test 要決定服務 fixture 的管理方式（Process.start / Docker / testcontainers）、健康檢查策略（port 可達 / HTTP health / 業務操作成功）、和狀態隔離方式（每 test 重啟 / 重設狀態 / 獨立 namespace）。成本判斷依據服務啟動成本和協議複雜度兩個維度。</p>
]]></content:encoded></item><item><title>Mock 遮蔽</title><link>https://tarrragon.github.io/blog/testing/knowledge-cards/mock-masking/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/testing/knowledge-cards/mock-masking/</guid><description>&lt;p>Mock 遮蔽的核心概念是「mock 忠實模擬程式語言的 API 契約，但跳過了協議層和環境層的行為差異，讓這些差異在 test 中不可見」。遮蔽是 mock 的設計邊界，遮蔽的範圍形成結構性的驗證盲區。可先對照 &lt;a href="https://tarrragon.github.io/blog/testing/knowledge-cards/protocol-integration-test/" data-link-title="Protocol Integration Test" data-link-desc="驗證程式碼和真實外部服務之間的協議互動是否正確的 test 層級">protocol integration test&lt;/a> 和&lt;a href="https://tarrragon.github.io/blog/testing/knowledge-cards/nominal-integration-test/" data-link-title="名義 Integration Test" data-link-desc="名稱含 integration 但核心依賴全用 fake 的 test，驗證內部狀態機而非真實服務互動">名義 integration test&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Mock 遮蔽發生在 API 層和協議層之間的語意斷裂處。Mock 模擬的是最上層（方法簽名、參數型別、回傳值），真實行為發生在下面兩層（協議語意、執行環境）。遮蔽有兩種模式：功能存在但行為錯誤（mock 接受了真實服務不接受的輸入）、功能根本沒實作（mock 不需要該功能就能通過）。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>Mock 遮蔽的訊號是：test 全過但實機失敗的 bug 類型集中在外部互動（連線、認證、編碼）、修復後原有 test 不需要改動、bug 修復是型別轉換或編碼調整。&lt;code>FakeWebSocketChannel&lt;/code> 的 &lt;code>sink.add(dynamic)&lt;/code> 不區分 text/binary frame 是典型案例。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>面對 mock 遮蔽的正確策略是分層驗證 — mock 負責 API 層，&lt;a href="https://tarrragon.github.io/blog/testing/knowledge-cards/protocol-integration-test/" data-link-title="Protocol Integration Test" data-link-desc="驗證程式碼和真實外部服務之間的協議互動是否正確的 test 層級">protocol integration test&lt;/a> 負責協議層。增加 mock test 數量無法跨越層級盲區。Mock 也不應該模擬協議行為 — 讓 mock 更「逼真」會讓 mock 本身變成需要維護和驗證的複雜元件。&lt;/p></description><content:encoded><![CDATA[<p>Mock 遮蔽的核心概念是「mock 忠實模擬程式語言的 API 契約，但跳過了協議層和環境層的行為差異，讓這些差異在 test 中不可見」。遮蔽是 mock 的設計邊界，遮蔽的範圍形成結構性的驗證盲區。可先對照 <a href="/blog/testing/knowledge-cards/protocol-integration-test/" data-link-title="Protocol Integration Test" data-link-desc="驗證程式碼和真實外部服務之間的協議互動是否正確的 test 層級">protocol integration test</a> 和<a href="/blog/testing/knowledge-cards/nominal-integration-test/" data-link-title="名義 Integration Test" data-link-desc="名稱含 integration 但核心依賴全用 fake 的 test，驗證內部狀態機而非真實服務互動">名義 integration test</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Mock 遮蔽發生在 API 層和協議層之間的語意斷裂處。Mock 模擬的是最上層（方法簽名、參數型別、回傳值），真實行為發生在下面兩層（協議語意、執行環境）。遮蔽有兩種模式：功能存在但行為錯誤（mock 接受了真實服務不接受的輸入）、功能根本沒實作（mock 不需要該功能就能通過）。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>Mock 遮蔽的訊號是：test 全過但實機失敗的 bug 類型集中在外部互動（連線、認證、編碼）、修復後原有 test 不需要改動、bug 修復是型別轉換或編碼調整。<code>FakeWebSocketChannel</code> 的 <code>sink.add(dynamic)</code> 不區分 text/binary frame 是典型案例。</p>
<h2 id="設計責任">設計責任</h2>
<p>面對 mock 遮蔽的正確策略是分層驗證 — mock 負責 API 層，<a href="/blog/testing/knowledge-cards/protocol-integration-test/" data-link-title="Protocol Integration Test" data-link-desc="驗證程式碼和真實外部服務之間的協議互動是否正確的 test 層級">protocol integration test</a> 負責協議層。增加 mock test 數量無法跨越層級盲區。Mock 也不應該模擬協議行為 — 讓 mock 更「逼真」會讓 mock 本身變成需要維護和驗證的複雜元件。</p>
]]></content:encoded></item><item><title>名義 Integration Test</title><link>https://tarrragon.github.io/blog/testing/knowledge-cards/nominal-integration-test/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/testing/knowledge-cards/nominal-integration-test/</guid><description>&lt;p>名義 integration test 的核心概念是「test 標題或路徑包含 integration，但所有外部依賴都被 fake 替換，實際驗證的是內部邏輯而非真實服務互動」。它的問題在命名造成的認知偏差 — 團隊以為 integration 已驗證，實際上協議層完全沒被覆蓋。可先對照 &lt;a href="https://tarrragon.github.io/blog/testing/knowledge-cards/mock-masking/" data-link-title="Mock 遮蔽" data-link-desc="mock 模擬 API 層但不模擬協議層，造成的結構性驗證盲區">mock 遮蔽&lt;/a>和 &lt;a href="https://tarrragon.github.io/blog/testing/knowledge-cards/protocol-integration-test/" data-link-title="Protocol Integration Test" data-link-desc="驗證程式碼和真實外部服務之間的協議互動是否正確的 test 層級">protocol integration test&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>名義 integration test 在 test 分類中介於 unit test 和真正的 integration test 之間。它的 scope 比 unit test 大（多個內部元件一起測），但驗證對象和 unit test 相同（程式碼內部邏輯）。它和 &lt;a href="https://tarrragon.github.io/blog/testing/knowledge-cards/mock-masking/" data-link-title="Mock 遮蔽" data-link-desc="mock 模擬 API 層但不模擬協議層，造成的結構性驗證盲區">mock 遮蔽&lt;/a>的關係是：名義 integration test 用 mock 替換所有外部依賴，mock 遮蔽了協議層行為，而 test 名稱讓團隊以為這些行為已被驗證。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>辨識名義 integration test 的三個特徵：核心外部依賴 100% 被 fake 取代、沒有真實的 I/O 操作（網路、檔案、資料庫）、&lt;code>setUp()&lt;/code> 不需要啟動外部程序或建立網路連線。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>修正策略分兩步：改名（讓 test 名稱反映真實驗證對象，如 &lt;code>connection_state_machine_test&lt;/code>）和補寫（如果協議互動是關鍵路徑，補寫對真實服務的 &lt;a href="https://tarrragon.github.io/blog/testing/knowledge-cards/protocol-integration-test/" data-link-title="Protocol Integration Test" data-link-desc="驗證程式碼和真實外部服務之間的協議互動是否正確的 test 層級">protocol integration test&lt;/a>）。在 test 檔案頂部標明被 fake 取代的依賴清單，讓後續讀者快速判斷驗證邊界。&lt;/p></description><content:encoded><![CDATA[<p>名義 integration test 的核心概念是「test 標題或路徑包含 integration，但所有外部依賴都被 fake 替換，實際驗證的是內部邏輯而非真實服務互動」。它的問題在命名造成的認知偏差 — 團隊以為 integration 已驗證，實際上協議層完全沒被覆蓋。可先對照 <a href="/blog/testing/knowledge-cards/mock-masking/" data-link-title="Mock 遮蔽" data-link-desc="mock 模擬 API 層但不模擬協議層，造成的結構性驗證盲區">mock 遮蔽</a>和 <a href="/blog/testing/knowledge-cards/protocol-integration-test/" data-link-title="Protocol Integration Test" data-link-desc="驗證程式碼和真實外部服務之間的協議互動是否正確的 test 層級">protocol integration test</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>名義 integration test 在 test 分類中介於 unit test 和真正的 integration test 之間。它的 scope 比 unit test 大（多個內部元件一起測），但驗證對象和 unit test 相同（程式碼內部邏輯）。它和 <a href="/blog/testing/knowledge-cards/mock-masking/" data-link-title="Mock 遮蔽" data-link-desc="mock 模擬 API 層但不模擬協議層，造成的結構性驗證盲區">mock 遮蔽</a>的關係是：名義 integration test 用 mock 替換所有外部依賴，mock 遮蔽了協議層行為，而 test 名稱讓團隊以為這些行為已被驗證。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>辨識名義 integration test 的三個特徵：核心外部依賴 100% 被 fake 取代、沒有真實的 I/O 操作（網路、檔案、資料庫）、<code>setUp()</code> 不需要啟動外部程序或建立網路連線。</p>
<h2 id="設計責任">設計責任</h2>
<p>修正策略分兩步：改名（讓 test 名稱反映真實驗證對象，如 <code>connection_state_machine_test</code>）和補寫（如果協議互動是關鍵路徑，補寫對真實服務的 <a href="/blog/testing/knowledge-cards/protocol-integration-test/" data-link-title="Protocol Integration Test" data-link-desc="驗證程式碼和真實外部服務之間的協議互動是否正確的 test 層級">protocol integration test</a>）。在 test 檔案頂部標明被 fake 取代的依賴清單，讓後續讀者快速判斷驗證邊界。</p>
]]></content:encoded></item><item><title>Screen State Test</title><link>https://tarrragon.github.io/blog/testing/knowledge-cards/screen-state-test/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/testing/knowledge-cards/screen-state-test/</guid><description>&lt;p>Screen state test 的核心概念是「驗證畫面層級的狀態機是否完整 — 每個狀態下使用者看到什麼、能操作什麼、怎麼離開」。它的斷言對象是使用者可見的畫面，和 unit test（斷言函式回傳值）及 &lt;a href="https://tarrragon.github.io/blog/testing/knowledge-cards/protocol-integration-test/" data-link-title="Protocol Integration Test" data-link-desc="驗證程式碼和真實外部服務之間的協議互動是否正確的 test 層級">protocol integration test&lt;/a>（斷言協議互動）職責不同。可先對照&lt;a href="https://tarrragon.github.io/blog/ux-design/knowledge-cards/screen-state-matrix/" data-link-title="畫面狀態矩陣" data-link-desc="說明用四欄表格（顯示/可用操作/進入條件/退出路徑）系統性地暴露畫面導航缺口的設計工具">畫面狀態矩陣&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Screen state test 是測試三層中的第三層。Unit test 驗證程式碼邏輯，protocol integration test 驗證協議互動，screen state test 驗證畫面狀態。同一段程式碼可能 unit test 通過但 screen state test 失敗 — 因為 UI binding 的問題讓正確的邏輯沒有反映到畫面上。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 screen state test 的訊號是畫面有多個狀態（loading / connected / error / disconnected）且狀態轉換邏輯複雜。&lt;a href="https://tarrragon.github.io/blog/ux-design/knowledge-cards/screen-state-matrix/" data-link-title="畫面狀態矩陣" data-link-desc="說明用四欄表格（顯示/可用操作/進入條件/退出路徑）系統性地暴露畫面導航缺口的設計工具">畫面狀態矩陣&lt;/a>直接轉成 test case — 矩陣中每個狀態的「顯示」「可用操作」「退出路徑」各對應一個 assertion。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Screen state test 要決定用什麼工具驗證畫面（widget test / integration test / Playwright）、斷言的粒度（元素存在 / 文字內容 / 視覺比對）、和狀態的觸發方式（mock 觸發狀態切換 / 真實操作觸發）。&lt;/p></description><content:encoded><![CDATA[<p>Screen state test 的核心概念是「驗證畫面層級的狀態機是否完整 — 每個狀態下使用者看到什麼、能操作什麼、怎麼離開」。它的斷言對象是使用者可見的畫面，和 unit test（斷言函式回傳值）及 <a href="/blog/testing/knowledge-cards/protocol-integration-test/" data-link-title="Protocol Integration Test" data-link-desc="驗證程式碼和真實外部服務之間的協議互動是否正確的 test 層級">protocol integration test</a>（斷言協議互動）職責不同。可先對照<a href="/blog/ux-design/knowledge-cards/screen-state-matrix/" data-link-title="畫面狀態矩陣" data-link-desc="說明用四欄表格（顯示/可用操作/進入條件/退出路徑）系統性地暴露畫面導航缺口的設計工具">畫面狀態矩陣</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Screen state test 是測試三層中的第三層。Unit test 驗證程式碼邏輯，protocol integration test 驗證協議互動，screen state test 驗證畫面狀態。同一段程式碼可能 unit test 通過但 screen state test 失敗 — 因為 UI binding 的問題讓正確的邏輯沒有反映到畫面上。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 screen state test 的訊號是畫面有多個狀態（loading / connected / error / disconnected）且狀態轉換邏輯複雜。<a href="/blog/ux-design/knowledge-cards/screen-state-matrix/" data-link-title="畫面狀態矩陣" data-link-desc="說明用四欄表格（顯示/可用操作/進入條件/退出路徑）系統性地暴露畫面導航缺口的設計工具">畫面狀態矩陣</a>直接轉成 test case — 矩陣中每個狀態的「顯示」「可用操作」「退出路徑」各對應一個 assertion。</p>
<h2 id="設計責任">設計責任</h2>
<p>Screen state test 要決定用什麼工具驗證畫面（widget test / integration test / Playwright）、斷言的粒度（元素存在 / 文字內容 / 視覺比對）、和狀態的觸發方式（mock 觸發狀態切換 / 真實操作觸發）。</p>
]]></content:encoded></item></channel></rss>