當 TDD 遇上 AI 時代:一個開發者的覺醒之路

從需求定義者到程式碼實作者:一個 PM 轉職工程師的 TDD 與 EDD 領悟

開發者困惑於AI測試

三年前的我,坐在 Sprint Planning 會議上,看著工程師 Kevin 說他需要兩天時間來「重構購物車邏輯並補完測試案例」。

我當時心裡 OS:「這功能不是上個月才做好嗎?為什麼要重構?而且補測試要兩天?直接改程式碼不就好了?」

Kevin 看出我的疑惑,解釋說:「沒有測試的程式碼就像沒有地基的房子,改一個地方可能整棟垮掉。」

我點點頭,但心裡還是覺得工程師太龜毛。

直到那個專案出包的那天。

那個讓我決定轉職的 Bug

那是一個看似簡單的需求:把折扣計算邏輯從「滿千折百」改成「滿五百折五十」。

我寫了清楚的需求文件,開了 Jira ticket,設定優先級為 P1。工程師說「這很簡單,一個下午就好」。

結果上線當天,客服電話被打爆。

不是因為新的折扣邏輯有問題,而是修改折扣計算的時候,不小心動到了會員等級判斷的部分。結果所有 VIP 會員都無法享受專屬折扣,系統把他們當成一般會員處理。

我看著工程師 debug 到凌晨三點,突然想起 Kevin 說的那句話:「沒有測試的程式碼就像沒有地基的房子。」

那個晚上,我做了一個決定:我要學寫程式。

不是要轉職當工程師,只是想理解「為什麼改一個邏輯會影響到其他功能」、「為什麼測試這麼重要」。

結果越學越深,半年後,我真的遞出了轉職申請。

從 PRD 到 Test Case:我的第一次頓悟

轉職後的第一個月,技術主管丟給我一本書:《Test Driven Development: By Example》。

「先從 TDD 開始學,」他說,「這會幫你建立正確的思維模式。」

我翻開書,看到第一個範例是寫一個計算器。作者說要「先寫測試,再寫程式碼」。

我心想:這不就是我以前寫需求文件的邏輯嗎?

以前當 PM 寫的 User Story

As a 使用者
I want to 輸入兩個數字並選擇加法
So that 系統能顯示正確的計算結果

Acceptance Criteria:
- Given 使用者輸入 2 和 3
- When 選擇加法
- Then 系統顯示 5

現在當工程師寫的 Test Case

def test_addition():
    calculator = Calculator()
    result = calculator.add(2, 3)
    assert result == 5

欸,這根本是同一件事啊!

只是 PM 用自然語言寫,工程師用程式碼寫而已。

那個瞬間我突然理解了 TDD 的精髓:先定義「完成」的標準,再去實作功能。這不就是我做了三年的產品管理嗎?

我開始瘋狂練習 TDD。每次寫功能前,我都會先想:「如果我是 PM,我會怎麼寫這個驗收標準?」然後把它轉成測試案例。

Red(紅燈) = 需求還沒實現 Green(綠燈) = 功能符合驗收標準 Refactor(重構) = 在不改變需求的前提下優化實作

這個循環跟敏捷開發的節奏完美契合。

我甚至開始覺得,PM 轉工程師搞不好是優勢。因為我太習慣「先定義完成標準」這件事了,TDD 對我來說根本是直覺反應。

直到我接到第一個 AI 相關的需求。

無法定義的「驗收標準」

公司決定在客服系統加入 AI 問答功能。技術主管知道我以前是 PM,就把需求分析的工作也交給我。

我打開熟悉的 Notion,開始寫需求文件:

## User Story
As a 客戶
I want to 向 AI 客服詢問退貨流程
So that 我能快速了解如何退貨

## Acceptance Criteria
- Given 使用者輸入「如何退貨?」
- When 系統呼叫 AI 模型
- Then 系統回答「請在收到商品 7 天內...」

寫到這裡,我卡住了。

AI 的回答每次都不一樣。有時候它會說「收貨後七日內」,有時候說「7 天內」,有時候還會加上「記得保持商品完整喔」這種額外資訊。

我該怎麼寫 Acceptance Criteria?

以前當 PM 的時候,如果規格不明確,我會跟設計師或工程師討論,直到我們對「完成」有共識為止。但現在,我面對的是一個 LLM,它的輸出本質上就是不確定的。

我試著寫測試:

def test_ai_customer_service():
    bot = AICustomerService()
    response = bot.answer("如何退貨?")
    assert response == "請在收到商品 7 天內,保持商品完整,透過官網申請退貨。"

執行測試。紅燈。

我調整提示詞,再執行。還是紅燈。

但 AI 的回答明明是對的啊!只是用字不同而已。

我突然理解為什麼有些工程師會說「AI 應用很難測試」了。這不是技術問題,是我們無法用傳統的『二元判斷』來評估 AI 的輸出

作為 PM,我最怕的就是「需求不明確」。但現在,我遇到的是「無法明確定義驗收標準」的情況。

這比需求不明確還要慘。

PM 思維的反擊:從 KPI 到評估指標

那天晚上,我翻出以前當 PM 時做的 OKR 文件。

我記得當時公司要衡量「客服品質」,我設計了一套評估指標:

  • 首次回應時間 < 30 秒
  • 問題解決率 > 85%
  • 客戶滿意度 > 4.0/5.0
  • 平均對話輪數 < 5

等等,這不就是多維度評估嗎?

我沒有說「客服必須說『您好,我是客服專員 Alice,很高興為您服務』這句話」,而是定義了好的客服應該符合的標準

這跟 AI 的情況很像啊!

我不需要規定 AI 一定要回答什麼,我只需要定義「好的回答應該符合哪些標準」。

我開始重新設計測試策略:

class AIResponseEvaluator:
    """用 PM 思維設計的 AI 評估器"""

    def evaluate(self, question, answer, reference_answer):
        """
        多維度評估 AI 回答品質
        就像評估 KPI 一樣
        """
        scores = {}

        # KPI 1: 資訊準確性(類似業務指標)
        scores['accuracy'] = self._check_key_points(
            answer,
            required_keywords=["7 天", "完整", "申請"]
        )

        # KPI 2: 資訊完整性(類似覆蓋率指標)
        scores['completeness'] = self._compare_with_reference(
            answer,
            reference_answer
        )

        # KPI 3: 用戶體驗(類似滿意度指標)
        scores['user_experience'] = self._evaluate_tone(
            answer,
            expected_tone="friendly_and_professional"
        )

        # KPI 4: 效率指標(類似回應時間)
        scores['conciseness'] = self._check_word_count(
            answer,
            max_words=80
        )

        # 加權計算(就像 OKR 的權重設計)
        total_score = (
            scores['accuracy'] * 0.4 +
            scores['completeness'] * 0.3 +
            scores['user_experience'] * 0.2 +
            scores['conciseness'] * 0.1
        )

        return {
            'total_score': total_score,
            'breakdown': scores,
            'passed': total_score >= 0.8  # 80 分門檻
        }

這個設計讓我想起以前在 Google Analytics 設定轉換目標的邏輯。

你不會說「使用者一定要點擊這個按鈕」,而是定義「成功的使用者旅程應該包含哪些關鍵步驟」。

我開始用這套邏輯設計測試:

def test_ai_response_quality():
    """不測試確切內容,而是測試品質指標"""
    bot = AICustomerService()
    evaluator = AIResponseEvaluator()

    # 測試案例 1:退貨政策
    response = bot.answer("如何退貨?")
    result = evaluator.evaluate(
        question="如何退貨?",
        answer=response,
        reference_answer="請在收到商品 7 天內,保持商品完整,透過官網申請退貨。"
    )

    assert result['passed'], f"品質評分 {result['total_score']:.2f} 低於門檻"
    assert result['breakdown']['accuracy'] > 0.7, "關鍵資訊缺失"

    # 測試案例 2:運費計算
    response = bot.answer("運費怎麼算?")
    result = evaluator.evaluate(
        question="運費怎麼算?",
        answer=response,
        reference_answer="單筆訂單滿 1000 元免運,未滿收取 80 元運費。"
    )

    assert result['passed'], f"品質評分 {result['total_score']:.2f} 低於門檻"

第一次執行,平均分數 72 分。不及格。

我分析了低分案例,發現 AI 常常:

  1. 回答太冗長(沒有遵守簡潔性原則)
  2. 缺少具體數字(準確性不足)
  3. 語氣太正式或太口語化(用戶體驗不穩定)

這就跟我以前做 PM 時分析產品指標一樣。找出問題,優化,再測試。

我調整了提示詞:

system_prompt_v2 = """你是電商客服 AI,請遵循以下規範:

【資訊要求】
- 必須包含具體數字(天數、金額、百分比)
- 必須包含操作步驟

【語氣要求】
- 友善但專業
- 使用「您」而非「你」
- 適度使用表情符號增加親和力

【格式要求】
- 控制在 50 字以內
- 重點使用條列式
- 先講結論再講細節
"""

重新評估,平均分數跳到 89 分。

那個瞬間,我突然意識到:我不是在寫測試,我是在設計產品的品質標準。這跟我以前制定 PRD 裡的 Success Metrics 根本是同一件事。

後來我才知道,這套方法有個名字:Evaluation-Driven Development(評估驅動開發),簡稱 EDD。

TDD與EDD對比

兩個世界的融合

現在回想起來,我的 PM 背景反而成了優勢。

傳統工程師學 TDD → 要改變「先寫程式碼再測試」的習慣 PM 轉職工程師學 TDD → 只是把「寫驗收標準」換成「寫測試案例」

傳統工程師遇到 AI → 困惑於無法寫確定性測試 PM 轉職工程師遇到 AI → 直覺套用「多維度評估指標」的思維

我開始理解為什麼 IBM 和 Microsoft 的研究顯示,採用 TDD 的專案缺陷率能降低 40-90%。因為 TDD 的本質就是強迫你在寫程式前先想清楚「完成」的定義

這不就是 PM 每天在做的事嗎?

而 EDD 則是把評估標準從二元判斷擴展到多維度量化。這也是 PM 在設計 OKR 和 KPI 時的日常。

現在我的專案裡,TDD 和 EDD 和平共存:

TDD 部分(確定性邏輯):

def test_calculate_shipping_fee():
    """測試運費計算邏輯(確定性)"""
    order = Order(total=800)
    assert order.calculate_shipping() == 80

    order = Order(total=1200)
    assert order.calculate_shipping() == 0

EDD 部分(AI 生成內容):

def test_ai_recommendation_quality():
    """測試 AI 推薦品質(多維度評估)"""
    recommender = AIRecommender()
    evaluator = RecommendationEvaluator()

    products = recommender.suggest_for_user(user_id=123)
    score = evaluator.evaluate(
        recommendations=products,
        metrics=['relevance', 'diversity', 'novelty']
    )

    assert score['overall'] >= 0.85
    assert score['relevance'] >= 0.9  # 相關性要特別高

這兩種方法不是對立的,而是互補的。就像 PM 和工程師不是對立的,而是互補的一樣。

PM 轉 Coder 的獨特優勢

這一年多的轉職經驗,讓我發現 PM 背景帶來的幾個優勢:

1. 對「為什麼」的執著

工程師容易陷入「怎麼做」的細節,但 PM 訓練讓我總是先問「為什麼要做」。

寫測試時,我不會機械性地覆蓋所有分支,而是先問:

  • 這個功能的核心價值是什麼?
  • 用戶最在意的是哪個部分?
  • 什麼情況下的失敗會造成最大損失?

這讓我的測試更聚焦在關鍵路徑上。

2. 對用戶體驗的敏感度

設計 AI 評估指標時,很多工程師會糾結於技術指標(如 BLEU score、ROUGE score)。

但我會問:「用戶真的在乎這個嗎?」

所以我設計的評估指標通常包含:

  • 回答是否解決了用戶的問題(任務完成率)
  • 用戶是否需要追問(對話效率)
  • 用戶是否感到被尊重(情感體驗)

這些都是從產品角度出發的指標。

3. 對 Trade-off 的理解

PM 最常做的就是優先級排序和取捨。

這讓我在設計評估指標時,不會追求「完美」,而是追求「適合當前階段的好」。

例如,MVP 階段我可能只測試核心功能的準確性;產品成熟後才加入語氣、簡潔度等細緻指標。

4. 文檔化的習慣

PM 出身的我,註解和 README 寫得特別詳細。

這在團隊協作時特別有用,新人看我的測試案例,就能理解這個功能要達成什麼目的。

def test_refund_eligibility():
    """
    測試退款資格判斷邏輯

    Business Context:
    - 根據 2024 Q1 客訴分析,退款糾紛主要來自「收貨時間」認定
    - 此測試確保系統正確計算 7 天鑑賞期

    Edge Cases:
    - 假日不計入鑑賞期
    - 預購商品從實際收貨日起算

    Related:
    - Jira: PROD-1234
    - Policy Doc: https://...
    """
    # 測試程式碼...

給其他想轉職的 PM 的建議

如果你也在考慮從 PM 轉工程師,我想分享幾個心得:

你的 PM 經驗不會白費

很多人轉職時會擔心「過去的經驗都用不上」。其實不是。

你學過的需求分析、用戶研究、指標設計,都能在工程實踐中派上用場。特別是在設計測試策略和評估指標時,PM 思維是巨大優勢。

從 TDD 開始學比較容易

因為 TDD 的思維模式跟寫 User Story 很像,PM 轉職者通常能很快上手。

這會給你信心,讓你覺得「我可以做好工程師的工作」。

不要丟掉產品思維

有些轉職者會矯枉過正,刻意壓抑產品思維,只想「當個純粹的工程師」。

但其實,懂產品的工程師在團隊裡非常稀缺。保留你的產品敏感度,這會讓你成為「能獨立思考的工程師」而不只是「執行需求的碼農」。

AI 時代對 PM 背景更友善

隨著 AI 應用越來越多,「如何評估 AI 的品質」成為新的挑戰。

這正是 PM 最擅長的:定義成功標準、設計評估指標、量化產品價值

所以如果你正在猶豫,這可能是最好的轉職時機。

工具推薦(實戰驗證過的)

TDD 工具

Python 生態

pip install pytest pytest-cov pytest-mock faker
  • pytest:測試框架,語法簡潔
  • pytest-cov:程式碼覆蓋率報告
  • pytest-mock:Mock 外部依賴
  • faker:生成測試資料(省得自己想)

學習資源

  • 《Test Driven Development: By Example》- Kent Beck(TDD 之父)
  • 線上課程:Test-Driven Development 101 (Udemy)

EDD 工具

Promptfoo(我目前主力):

npm install -g promptfoo

簡單的配置檔案就能跑批次評估:

prompts:
  - file://prompts/customer_service_v1.txt
  - file://prompts/customer_service_v2.txt

providers:
  - openai:gpt-4

tests:
  - vars:
      question: "如何退貨?"
    assert:
      - type: contains
        value: "7 天"
      - type: javascript
        value: output.length < 200  # 簡潔性
      - type: llm-rubric
        value: "回答是否友善且專業"

執行評估:

promptfoo eval

其他值得關注的工具

  • LangSmith:適合 LangChain 生態系統
  • DeepEval:輕量級,適合快速驗證
  • Weights & Biases:如果你需要追蹤模型訓練過程

寫在最後:從定義需求到定義品質

轉職這一年多,我最大的收穫不是學會了 Python 或 JavaScript,而是理解了開發方法論的本質

TDD 教我:在動手之前先想清楚目標。 EDD 教我:用多維度的標準取代二元的判斷

但其實,這些都是我當 PM 時就在做的事。

當 PM 時,我定義「什麼是成功的產品」。 當工程師時,我定義「什麼是合格的程式碼」。

形式不同,本質相同。

所以如果你也是 PM,正在考慮轉職,不用太擔心。你已經具備了很多工程思維,只是用不同的語言表達而已。

而如果你是工程師,我建議你花點時間理解 PM 的思維方式。特別是在 AI 時代,「如何定義品質」這件事,產品經理的經驗可能比傳統工程師更有幫助。

兩個世界的融合,或許能創造出更好的開發方法。

就像 TDD 和 EDD 的融合一樣。


延伸資源

關於 TDD

  • IBM/Microsoft 研究:TDD 降低 40-90% 缺陷率
  • Martin Fowler 的 TDD 實踐文章
  • Uncle Bob 的 Clean Code 系列

關於 EDD

  • arXiv 論文:《Challenges in Testing Large Language Model Based Applications》
  • Medium 系列:《Evaluation-Driven Development for Agentic Applications》
  • Promptfoo 官方文件:https://promptfoo.dev/

關於 PM 轉職

  • 《The Pragmatic Programmer》(實用主義程式設計師)
  • 《Refactoring》(重構:改善既有程式的設計)
  • Coding Interview University (GitHub)

社群資源

  • r/cscareerquestions(Reddit)
  • Blind(匿名職場社群)
  • TDD Practitioners(LinkedIn Group)

關於作者

一個從產品經理轉職工程師的學習者。曾經以為寫程式和寫需求文件是兩回事,後來發現它們都在回答同一個問題:「什麼是好的?」

現在的我,白天用 Python 寫程式,晚上用 Notion 整理筆記,周末會懷念開 Sprint Planning 的日子。

如果你也在轉職路上,歡迎留言交流。我們都是路上的同伴。


留言討論

你是 PM 轉職工程師嗎?或是工程師想轉 PM? 你覺得兩種角色最大的差異是什麼? 在 AI 開發上,你遇到了哪些挑戰?

歡迎在下方留言分享你的經驗。


標籤:#PM轉職 #工程師 #TDD #EDD #測試驅動開發 #評估驅動開發 #AI開發 #職涯轉換 #產品經理


本文最初發布於 HackMD @BASHCAT

留言

這個網誌中的熱門文章

Arduino 課本可能沒教的事(1)

SI4432 搭配Arduino

燒錄 Arduino mini Pro 燒錄