<?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>單元測試 on Tarragon</title><link>https://tarrragon.github.io/blog/tags/%E5%96%AE%E5%85%83%E6%B8%AC%E8%A9%A6/</link><description>Recent content in 單元測試 on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Wed, 04 Mar 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/%E5%96%AE%E5%85%83%E6%B8%AC%E8%A9%A6/index.xml" rel="self" type="application/rss+xml"/><item><title>混合測試策略：根據架構層級選擇測試方法</title><link>https://tarrragon.github.io/blog/record/%E6%B7%B7%E5%90%88%E6%B8%AC%E8%A9%A6%E7%AD%96%E7%95%A5%E6%A0%B9%E6%93%9A%E6%9E%B6%E6%A7%8B%E5%B1%A4%E7%B4%9A%E9%81%B8%E6%93%87%E6%B8%AC%E8%A9%A6%E6%96%B9%E6%B3%95/</link><pubDate>Wed, 04 Mar 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/record/%E6%B7%B7%E5%90%88%E6%B8%AC%E8%A9%A6%E7%AD%96%E7%95%A5%E6%A0%B9%E6%93%9A%E6%9E%B6%E6%A7%8B%E5%B1%A4%E7%B4%9A%E9%81%B8%E6%93%87%E6%B8%AC%E8%A9%A6%E6%96%B9%E6%B3%95/</guid><description>&lt;p>開始實踐 TDD 時，我們遇到一個困惑的問題：什麼都測，還是只測部分？&lt;/p>
&lt;p>追求覆蓋率，會寫出大量測試 getter 和直接欄位映射的測試，維護成本高，保護力低。不管覆蓋率，又很難有信心說業務邏輯正確。&lt;/p>
&lt;p>答案是：測試策略跟著架構走。&lt;/p></description><content:encoded><![CDATA[<p>開始實踐 TDD 時，我們遇到一個困惑的問題：什麼都測，還是只測部分？</p>
<p>追求覆蓋率，會寫出大量測試 getter 和直接欄位映射的測試，維護成本高，保護力低。不管覆蓋率，又很難有信心說業務邏輯正確。</p>
<p>答案是：測試策略跟著架構走。</p>
<h2 id="問題的根源">問題的根源</h2>
<p>全面單元測試的問題是，重構 ViewModel 內部實作時，大量測試跟著壞掉，但行為根本沒變。全面 BDD 的問題是，Domain 層邊界條件很難透過業務語言的場景完整覆蓋。</p>
<p>不同層級的程式碼，用不同的測試方法。</p>
<h2 id="五層架構的測試分工">五層架構的測試分工</h2>
<p><strong>Layer 1（UI/Presentation）</strong> 只針對關鍵互動流程撰寫整合測試。判斷標準：流程失敗是否影響核心業務、是否需要多步驟操作、是否涉及金流或敏感資料。靜態展示頁面、簡單列表交給人工測試。</p>
<p><strong>Layer 2（Application/Behavior）</strong> 只針對複雜轉換邏輯撰寫單元測試。判斷標準：轉換是否包含條件判斷、計算邏輯、多個來源資料，或邏輯超過十行。簡單的 DTO 欄位直接映射，不需要獨立測試，由 UseCase 層間接覆蓋。</p>
<p><strong>Layer 3（UseCase）</strong> 所有業務場景都必須撰寫 BDD 測試，沒有例外。每個 UseCase 至少涵蓋一個正常流程、兩個異常流程、三個邊界條件。格式使用 Given-When-Then，只 Mock 外層依賴，使用真實的 Domain Entity。</p>
<p><strong>Layer 4（Interface）</strong> 不測試。介面只定義合約，沒有可測試的行為。</p>
<p><strong>Layer 5（Domain Implementation）</strong> 複雜業務規則必須撰寫單元測試。判斷標準：是否包含業務規則驗證、計算邏輯、狀態轉換、不變量檢查。Email 格式驗證、金額範圍、訂單狀態轉換都需要完整的單元測試。純資料容器的 Entity 不需要獨立測試。</p>
<h2 id="做決策的流程">做決策的流程</h2>
<p>確定程式碼屬於哪一層（目錄結構直接反映架構層級），然後問一個問題：</p>
<ul>
<li>UI 層：這是關鍵互動流程嗎？</li>
<li>Behavior 層：這裡有複雜轉換邏輯嗎？</li>
<li>UseCase 層：直接寫 BDD 測試。</li>
<li>Interface 層：不測試。</li>
<li>Domain 層：這裡有複雜業務規則嗎？</li>
</ul>
<p>答案是就寫，不是就跳過讓上層覆蓋。</p>
<h2 id="技術性測試項目">技術性測試項目</h2>
<p>不分層級都要納入：</p>
<ul>
<li>Null 值和空集合</li>
<li>邊界值（零、負數、最大值）</li>
<li>異常處理（網路錯誤、儲存失敗）</li>
<li>資料驗證（格式、範圍、必填欄位）</li>
</ul>
<p>這些容易被忽略，但往往是上線後出問題的地方。</p>
<h2 id="覆蓋率的意義">覆蓋率的意義</h2>
<p>這套策略讓覆蓋率指標更有意義。UseCase 層要求行為場景覆蓋率 100%，是所有業務場景都有測試，不是追求程式碼行數百分比。Domain 層複雜邏輯要求分支覆蓋率 100%，每個分支都代表一個業務決策。整體新增程式碼維持 80% 以上。</p>
<p>數字背後有實際意義，不是為了報告好看。</p>
<h2 id="測試的穩定性">測試的穩定性</h2>
<p>UseCase 層的 BDD 測試關注行為，重構內部邏輯只要業務行為沒變，測試就不需要動。Domain 層只有規則本身改變才需要更新。Behavior 層只測複雜的轉換邏輯，重構簡單映射不影響測試。</p>
<p>測試應該是開發的保護網，不是阻力。測試因為業務改變而失敗，那很好；因為重構而大量失敗，那是設計問題。</p>]]></content:encoded></item></channel></rss>