py程式設計(三)課程網站
第 15 週 · 單元 6-1 · 專案三

幫平台加上 AI 功能(下):不花錢也能測試 AI,然後上線

AI 每次回答都不一樣,又要花額度,要怎麼寫自動測試?答案是用「假的 AI」。本週完成每日上限、用假客戶端測試所有情況,最後部署並設定金鑰。

W15AI 功能測試+上線

本週結束時你會

今天的時間安排

0:00–0:30【自己做】每日上限
0:30–1:15【跟著做】用假的 AI 客戶端寫測試
1:15–1:25休息
1:25–2:00上線:Vercel 環境變數、線上驗收
2:00–2:30Demo、專案回顧、期末專題提案預告

每日上限【自己做】

需求:資料表 ai_usage(day, calls) 記錄每天呼叫次數;每次真的呼叫 API 前加 1;達到上限(環境變數 AI_DAILY_LIMIT,預設 50)時不呼叫,顯示「今天的 AI 使用次數已達上限」。

為什麼是全站上限,而不是每人上限:這個網站沒有登入,無法分辨是誰。全站上限是最後一道保險:就算有人寫程式狂按按鈕,一天最多也只會花 50 次的額度。

用假的 AI 客戶端寫測試【跟著做】

ai.summarize 有一個 client 參數。測試時傳入一個「長得像 Gemini 客戶端」的假物件:它不連網、回傳固定內容,還會記錄收到的提示詞,讓我們檢查 API 被呼叫了幾次、提示詞長什麼樣子。

提示詞 Antigravity
請在 tests/test_ai.py 寫 AI 摘要功能的測試,全部不可以真的呼叫 Gemini:
1. 寫一個 FakeClient 類別,模仿 google-genai 的 client.interactions.create(model, input):記錄每次收到的 input,回傳有 output_text 的物件;也可以設定成丟出錯誤
2. 測試前把 app.config["AI_CLIENT"] 換成 FakeClient
3. 測試這些情況:產生並顯示摘要;評論沒變時第二次不呼叫;新增評論後會重新呼叫;評論少於 3 則不呼叫;達到每日上限;AI 丟出錯誤時店家頁仍正常;含「忽略以上指示」的評論只出現在 <reviews> 區塊內;AI 回傳 <script> 時頁面有跳脫且長度被截斷;沒有金鑰時丟出 AIUnavailable
執行 python -m pytest -q。原本吃貨站的測試也要一起通過。

參考解答:原本吃貨站 17 項,加上 AI 功能 8 項,共 25 項全部通過。整套測試約 3 秒跑完,一毛錢都不花。

參考解答的測試(節錄概念)
class FakeClient:
    def __init__(self, reply="湯頭鮮甜最常被稱讚,缺點是要排隊。", error=None):
        self.prompts, self.reply, self.error = [], reply, error
        self.interactions = SimpleNamespace(create=self._create)

    def _create(self, model, input):
        self.prompts.append(input)          # 記錄提示詞,之後可以檢查
        if self.error:
            raise self.error                 # 模擬 AI 服務掛掉
        return SimpleNamespace(output_text=self.reply)

完整檔案:practice/s3-6-1_AI功能/參考解答/foodie-ai/tests/test_ai.py

製作參考解答時,注入測試一開始失敗:提示詞的說明文字本身也提到「<reviews> 標記」,測試抓到的是說明文字裡的那一個,而不是資料區塊。修正方式是取最後一組標記。這個例子很適合說明「測試失敗時,先確認是程式錯還是測試錯」。

上線

  1. 吃貨站要先完成第 8 週的做法:db.py 支援 Postgres、Vercel 連上 Neon,並在 Neon 建立 ai_summaries 與 ai_usage 兩張表。
  2. Vercel → Settings → Environment Variables,新增 GEMINI_API_KEY(自己貼上金鑰)與 SECRET_KEY,可選擇性新增 AI_DAILY_LIMIT。
  3. 重新部署,打開派森牛肉湯產生一次摘要。
線上驗收正確結果
產生摘要出現摘要,重新整理後仍在(存在 Neon)
Vercel 刪掉 GEMINI_API_KEY 再部署店家頁正常,只有摘要顯示暫時無法使用
GitHub 上搜尋金鑰的前幾個字元找不到

本週檢核

驗證紀錄:參考解答的 25 項測試全部通過(google-genai 2.31)。真正的 Gemini API 需要個人金鑰,參考解答沒有實際呼叫;請老師在課前用自己的金鑰執行一次 ai_hello,確認目前可用的模型名稱。

第 16 週預告:期末專題提案。請帶著第 2 週寫的 PROJECT.md 初稿來。