---
# System prepended metadata

title: 遺留的程式碼
tags: [單元測試的藝術]

---

# 遺留的程式碼

## 為什麼會不想使用測試驅動開發

- 很難給已存在的程式碼撰寫測試程式。
- 幾乎不可能或是沒有時間重構現有程式碼。
- 不想修改設計。
- 工具使用不便或是沒有可以使用的設計。
- 難以決定從什麼地方開始測試。

## 從哪裡開始加入測試

- **邏輯複雜度**：組件中邏輯的數量，如巢狀的if語句、switch case或遞迴。
- **依賴程度**：組件中依賴項的數量。
- **優先級**：在專案中的優先等級。

## 簡單的測試可行性表格

| 組件         | 邏輯複雜度 | 依賴數量 | 優先級 | 備註                                                                 |
|--------------|------------|----------|--------|----------------------------------------------------------------------|
| Utils        | 6          | 1        | 5      | 這個工具列的依賴項很少，但是包含很多邏輯，這個邏輯容易測試，很有價值。 |
| Person       | 2          | 1        | 1      | 這是一個資料列，邏輯簡單，沒有依賴項。                              |
| TextParser   | 8          | 4        | 6      | 這個類別邏輯複雜，依賴數量多，而且還是專案中高優先級的任務，測試這個類很有價值，但是測試難度高且費時。 |
| ConfigManager| 1          | 6        | 1      | 這個類別保存設定的資料，從硬碟讀取檔案。他的邏輯數量很少，但是依賴數量很多，測試這個類別對專案的價值很小，且測試難度高、費時。 |

## 決定選擇策略

- **先易後難測試的優缺點**：前期可能很快，但後期期限快到的時候，容易因為測試的內容複雜，導致壓力很大。
- **先難後易測試的優缺點**：對有經驗的團隊來說會是不錯的選擇。

## 在重構前撰寫整合測試

- 給系統新增一個或多個整合測試，不使用虛設常式或假物件，證明原本的系統運作正常。
- 重構，或是替要新增的功能撰寫一個失敗的測試。
- 對系統進行多次的重構和修改，每次只做少量的修改，並且盡可能多次執行整合測試。

## 針對遺留程式碼進行單元測試的重要工具

- 使用JustMock或Typemock Isolator輕鬆隔離依賴項。
- 使用JMock測試Java遺留程式碼。
- 重構Java程式碼時使用Vise。
- 重購前使用FitNeese進行驗收測試。
- 閱讀Michael Feathers 關於遺留程式碼的書(Working Effectively with legacy code)。
- 使用NDepend分析產品程式碼。
- 使用ReSharper更容易地瀏覽和重構產品程式碼。
- 使用Simian和TeamCity檢查重複的程式碼(和bug)。


## 我們可以使用的工具

- PHPUnit、Mockery已經可以做到隔離依賴項跟測試遺留程式碼。
- 自動化驗收測試工具:[Selenium](https://www.selenium.dev/)。
- PHP程式碼的分析工具可以使用[PHPInsights](https://phpinsights.com/)。


## 小結

了解各個組件的依賴數量、邏輯複雜度以及在專案中的優先等級來選擇要測試的組件。如果團隊沒有單元測試的經驗，或是單元測試的經驗比較少，應該先從簡單的組件開始著手，隨著測試的經驗愈來愈多，團隊的信心也會因此增強；若單元測試的經驗豐富，則反之，可以從複雜的組件開始進行。若不想重構又想進行單元測試，使用一些不受限的隔離框架可以提供很好的幫助。還有一些可以保護程式碼品質的工具可以使用，可以自行選擇什麼時候該使用什麼工具。

## 問題討論

+ 請依照上方的測試可行性表格，針對目前的專案簡單做出一份相同的表格

| 組件         | 邏輯複雜度 | 依賴數量 | 優先級 | 備註                                                         |
|--------------|------------|----------|--------|--------------------------------------------------------------|
| [組件名稱]   | [數值]     | [數值]   | [數值] | [對此組件的簡短描述，包括為什麼它適合/不適合進行測試]          |
+ 接上題，你會如何決定選擇策略，為什麼?