TDD(測試驅動開發)經典三定律:先寫失敗測試、最小實現、重構。但在真實項目中,盲目遵循「測試名必須英文」、「一次寫一個測試」、「一個測試一個斷言」等教條,往往降低團隊效率。本文分享海員管理系統項目中三個「違反教條但極大提升交付效率」的務實實踐。
業務領域術語(如「二副二管輪」、「中專」、「見習三副」)英文翻譯要么不存在,要么歧義極大。強行翻譯導致:
test_should_return_NOT_pass_if_duty_higher_than_second_mate... 讀不懂
// 重構前
public void test_should_return_NOT_pass_if_duty_higher_than_second_mate_or_second_engineer_and_education_level_is_secondary_and_guraduated_after_2002_02_01() { ... }
// 重構後
public void test_應該算未通過_if_職務高於二副二管輪_而_學歷只是中專_並且_畢業時間晚於2002年2月1日() { ... }
public void test_見習三副應該參加三副的培訓() { ... }
| 維度 | 堅持英文 | 採用中文 |
|---|---|---|
| 團隊英語水平 | 良好 | 一般,領域詞彙缺失 |
| 業務參與度 | 低 | 高(PO 直接讀測試名驗收) |
| 國際化計劃 | 近期有外籍成員 | 可預見未來無外籍成員 |
| 表達精確度 | 翻譯失真 | 與驗收條件逐字對應 |
結論:代碼的核心功能之一是「交流」。對於非國際化團隊,中文測試名是最高效的業務溝通載體,收益遠大於「違反慣例」的成本。
TDD 強調「小步前進、一紅一綠」,但實際中常漏寫邊界條件,導致功能上線後發現驗收遺漏。
public void test_會被認為不服從調配_if_海員在當前職位上曾經曠工() { /* TODO */ }
public void test_會被認為不服從調配_if_海員在當前職位上曾經請過病假() { /* TODO */ }
public void test_會被認為不服從調配_if_海員在當前職位上曾經請過事假() { /* TODO */ }
public void test_會被認為不服從調配_if_海員在當前職位上曾經被遣返() { /* TODO */ }
public void test_不會被認為不服從調配_if_海員在當前職位上從未曠工_請病假_請事假_和遣返() { /* TODO */ }
// TODO 持續提醒「還有測試未實現」。「這違反 TDD 一紅一綠節奏?」
不。TDD 核心是「測試先行驅動設計」,而非「一次只能有一個紅測試」。預寫名單只是將「思考驗收條件」前置,實現階段依然一個個填充綠燈。
Selenium/UI 測試中,啟動瀏覽器、登錄、導航到頁面(Setup)耗時秒級。每個測試獨立 Setup 導致測試套件運行極慢。
@Test
public void test_待辦任務頁面應顯示步驟詳情() throws Exception {
TodoItemPage page = navigator.gotoTodoItemPage(); // 單次昂貴 Setup
should_show_step_name_as_page_title(activeStep, page);
should_show_start_button_if_waiting(page);
should_show_transition_buttons(activeStep, page);
should_NOT_ask_opinion_if_not_processing(page);
should_show_comment_box_after_click_start(page);
}
private void should_show_step_name_as_page_title(FlowStep step, TodoItemPage page) {
assertEquals(step.getName(), page.title());
}
private void should_show_start_button_if_waiting(TodoItemPage page) {
assertTrue(page.isStartProcessingButtonVisible());
}
// ... 其他斷言方法
| 方案 | Setup 開銷 | 可讀性 | 失敗定位 | 維護成本 |
|---|---|---|---|---|
| 每個斷言一個 @Test + 獨立 Setup | 極高 | 高 | 精準 | 高(重復 Setup 代碼) |
| 一個 @Test 多個 assert 直接寫 | 低 | 低(長方法難讀) | 模糊(行號) | 低 |
| 本文方案:聚合測試 + 提煉斷言方法 | 低 | 高(方法名即文檔) | 精準(方法名) | 低 |
三個實踐的共同點:
TDD 不是儀式,是工程手段。當約束條件變化時,敢於「違反」教條並發明更適合當下上下文的實踐,才是資深工程師的標誌。