From 3e1cf9b980db55a6566a0df44123951278ddf84d Mon Sep 17 00:00:00 2001 From: August Chao Date: Wed, 10 Jun 2026 23:44:08 +0800 Subject: [PATCH] =?UTF-8?q?Trim=200611=20=E6=95=99=E6=9D=90=E4=B8=AD?= =?UTF-8?q?=E9=81=8E=E5=A4=9A=E7=9A=84=E6=8F=90=E7=A4=BA,=E8=90=BD?= =?UTF-8?q?=E5=AF=A6=E3=80=8C=E6=8F=90=E7=A4=BA=E8=A9=9E=E8=87=AA=E5=B7=B1?= =?UTF-8?q?=E6=89=93=E3=80=8D=E5=8E=9F=E5=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 lab 教案的設計提示與必備測試逐條列舉,改為「規格每條都要覆蓋,自己驗收」 - 移除 starter 測試骨架內每個測試的提示註解,保留規格與流程待辦 - 保留環境限制類資訊(matplotlib Agg)與 subTest 共用測試的架構要求 Co-Authored-By: Claude Fable 5 --- weeks/week-16/in_class/0611-sort-lab.md | 11 ++++------- .../in_class/0611-sort-starter/test_sorts.py | 18 ++++++------------ .../in_class/0611-sort-starter/test_timing.py | 3 --- 3 files changed, 10 insertions(+), 22 deletions(-) diff --git a/weeks/week-16/in_class/0611-sort-lab.md b/weeks/week-16/in_class/0611-sort-lab.md index 484c6d72b..f9ff6152a 100644 --- a/weeks/week-16/in_class/0611-sort-lab.md +++ b/weeks/week-16/in_class/0611-sort-lab.md @@ -37,10 +37,7 @@ - `f.records` — 歷次耗時的 list(累積) - 裝飾器內**不准 `print`**——輸出格式化是 benchmark 的事,計時器保持安靜才能被重複利用 -> 設計提示:`last_elapsed` 和 `records` 掛在 wrapper 函式物件上。 -> 想想看:為什麼掛在 wrapper 上而不是用全域變數?(這題會出現在課末檢測) - -**必備 test case(≥3)**:回傳值不變、`__name__` 保留、呼叫後 `last_elapsed > 0` 且 `records` 長度遞增。 +**必備 test case(≥3)**:規格的每一條都要有測試覆蓋。AI 給的測試齊不齊,自己驗收。 ## Stage 2|三種排序 + 量測(課堂 0:25–1:10) @@ -55,8 +52,8 @@ def merge_sort(data: list) -> list: ... - 一律**回傳新的 list,不可修改傳入的 list**(測試會驗) - **禁用** `sorted()` / `list.sort()`——那是 Stage 3 的對照組 -**必備 test case(每個函式都要過)**:空 list、單元素、含重複值、反向排序、隨機資料與 `sorted()` 結果比對、原 list 未被修改。 -三個函式共用同一組測試——用迴圈 + `subTest`,不要複製貼上三份。 +**必備 test case(每個函式都要過)**:一般案例之外,edge case 自己想(空的?重複?已排好?), +「不可修改傳入 list」也要有測試。三個函式共用同一組測試——用迴圈 + `subTest`,不要複製貼上三份。 接著寫 `benchmark.py`: @@ -91,7 +88,7 @@ def plot_results(results: dict, out_path: str) -> None: ... - 折線圖:x 軸 = 資料量 n,y 軸 = 平均秒數(**y 軸用 log scale**,不然 O(n²) 會把其他線壓扁) - 每個演算法一條線(含 baseline 與加速版),輸出 `assets/benchmark.png` -- 測試提示:用 `tempfile` 驗證 PNG 有產生且大小 > 0;`plot.py` 開頭加 `matplotlib.use("Agg")` 才能在無視窗環境(含 CI)跑 +- 測試需驗證 PNG 確實產生且非空檔;環境限制:`plot.py` 開頭加 `matplotlib.use("Agg")` 才能在無視窗環境跑 - 在你的 `README.md` 貼圖並用 2–3 句解讀:誰最快?O(n²) 和 O(n log n) 的線斜率差在哪?加速比多少? --- diff --git a/weeks/week-16/in_class/0611-sort-starter/test_sorts.py b/weeks/week-16/in_class/0611-sort-starter/test_sorts.py index 4456a8602..bae18961c 100644 --- a/weeks/week-16/in_class/0611-sort-starter/test_sorts.py +++ b/weeks/week-16/in_class/0611-sort-starter/test_sorts.py @@ -2,13 +2,14 @@ 規格:sorts.py 的 bubble_sort / quick_sort / merge_sort 必須 1. 回傳新的排序後 list,不可修改傳入的 list - 2. 禁用內建 sorted() / list.sort()(那是 Stage 3 的對照組) + 2. 禁用內建 sorted() / list.sort()(那是 Stage 3 的對照組; + 測試裡拿 sorted() 當驗證標準則可以) 設計要求:三個函式共用同一組測試——用迴圈 + subTest,不要複製貼上三份。 待辦: - 1. 自己打提示詞跟 AI 討論,補齊測試: - 空 list、單元素、重複值、反向、隨機資料比對、原 list 未被修改 + 1. 自己打提示詞跟 AI 討論,補齊測試——一般案例、edge case、 + 「不可修改傳入 list」都要覆蓋;AI 給的齊不齊,自己驗收 2. 跑 `python -m unittest` 確認全紅 3. commit: "test: stage2 排序正確性測試" 4. 寫 sorts.py,全綠後 commit: "feat: stage2 實作三種排序與 benchmark" @@ -18,26 +19,19 @@ # from sorts import bubble_sort, quick_sort, merge_sort # 完成 sorts.py 後解除註解 -# 提示:把三個排序函式放進一個 list,每個測試用 -# for sort_fn in SORT_FUNCTIONS: -# with self.subTest(sort_fn.__name__): -# ... -# Stage 3 的加速版只要 append 進這個 list 就能吃到同一組測試。 +# 三個排序函式都放進這個 list,每個測試用 subTest 跑一輪; +# Stage 3 的加速版 append 進來就能吃到同一組測試。 SORT_FUNCTIONS = [] # 解除上面 import 後填入 class TestSortFunctions(unittest.TestCase): def test_basic_cases(self): - # 提示:空 list、單元素、重複值、反向排序 self.fail("尚未實作 — 自己打提示詞跟 AI 討論後補上") def test_random_data_matches_builtin(self): - # 提示:random.seed 固定後產生資料,結果與 sorted() 比對 - # (測試裡可以用 sorted() 當「驗證標準」,被測函式裡不行) self.fail("尚未實作") def test_input_not_mutated(self): - # 提示:排序前先複製一份,排序後驗證原 list 沒變 self.fail("尚未實作") diff --git a/weeks/week-16/in_class/0611-sort-starter/test_timing.py b/weeks/week-16/in_class/0611-sort-starter/test_timing.py index 219877f93..d0fef1af6 100644 --- a/weeks/week-16/in_class/0611-sort-starter/test_timing.py +++ b/weeks/week-16/in_class/0611-sort-starter/test_timing.py @@ -20,15 +20,12 @@ class TestTimeit(unittest.TestCase): def test_returns_original_result(self): - # 提示:裝飾一個簡單函式(例如回傳 a + b),驗證回傳值不變 self.fail("尚未實作 — 自己打提示詞跟 AI 討論後補上") def test_preserves_function_metadata(self): - # 提示:驗證 __name__ 不是 'wrapper' self.fail("尚未實作") def test_records_elapsed_time(self): - # 提示:呼叫兩次,驗證 last_elapsed > 0 且 records 長度為 2 self.fail("尚未實作")