首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

TDD 實踐中的務實取捨:中文測試命名、預寫測試清單與多斷言共享 Fixture

     編輯:Java 相關知識

前言:原則服務於交付,而非教條

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 */ }

機制優勢

  1. 零成本備忘:空方法體測試天然通過,不阻塞 CI/CD,但 IDE 中灰色 // TODO 持續提醒「還有測試未實現」。
  2. 需求即代碼:驗收條件直接映射為測試名,無需切換文檔。
  3. 安全重構:需求變更時,刪除/修改方法名成本極低(無實現代碼)。
  4. Pair Programming 傳遞:接手開發者讀方法名即知剩餘工作,無需口頭交接。

常見質疑回應

「這違反 TDD 一紅一綠節奏?」

不。TDD 核心是「測試先行驅動設計」,而非「一次只能有一個紅測試」。預寫名單只是將「思考驗收條件」前置,實現階段依然一個個填充綠燈。

實踐三:一個 Fixture,多個斷言 —— 共享昂貴 Setup,保留精準描述

痛點

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 僅執行一次,多個斷言複用頁面對象
  • 失敗定位:斷言方法名出現在堆疊跟蹤中,依然清晰定位失敗點

對比傳統方案

方案Setup 開銷可讀性失敗定位維護成本
每個斷言一個 @Test + 獨立 Setup極高高精準高(重復 Setup 代碼)
一個 @Test 多個 assert 直接寫低低(長方法難讀)模糊(行號)低
本文方案:聚合測試 + 提煉斷言方法低高(方法名即文檔)精準(方法名)低

總結:務實的本質是「守住核心價值,靈活調整外在形式」

三個實踐的共同點:

  1. 核心價值不變:測試先行、需求可追溯、快速反饋、可維護性
  2. 外在形式妥協:命名語言、測試粒度、斷言組織方式
  3. 決策依據具體:團隊能力、業務特點、工具鏈現狀、成本收益分析

TDD 不是儀式,是工程手段。當約束條件變化時,敢於「違反」教條並發明更適合當下上下文的實踐,才是資深工程師的標誌。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved