標籤:生產 col 導致 dev 技術分享 開發人員 初始化 程式 改善
建議155:隨生產代碼一起提交單元測試代碼
首先提出一個問題:我們害怕修改代碼嗎?是否曾經無數次面對亂糟糟的代碼,下決心進行重構,然後在一個月後的某個周一,卻收到來自測試版的報告:新的版本,沒有之前的版本穩定,效能也更差了,Bug似乎也變多了。也就是說,重構的代碼看上去品質更高了,可實際測試結果卻不如人意。
幾乎每個程式員都因為此類問題糾結過。我們要修改的代碼也許來自某些不負責任或經驗欠佳的程式員,也許這些代碼是自己一年前寫的,但是看上去已經慘不忍睹。我們想要修改這些代碼,卻擔心重構出別的問題。即便是一個開發週期中的產品,也會有這樣的選擇出現。某個模組可能已經提交測試並確認通過,不過現在發現有更優的演算法和邏輯,改還是不改,成了一個問題。
“單元測試”減輕甚至消除了開發人員這種恐懼。如果項目沒有測試代碼,說明我們只是生產“定時炸彈”。很多人將生產代碼和測試代碼分別對待,這是一種過時的做法。程式員在提交自己的生產代碼時,必須同時提交自己的單元測試代碼。很多現代化的版本管理工具可以在後台訂製項目構建計劃,自動運行測試專案,統計程式碼涵蓋範圍,並產生相應報告。我們應該在早上一邊喝咖啡,一邊讀取這樣的報告。
有了測試代碼做保證,在很大程度上我們可以放心去重構了。如果某個功能偏離了既有成果,就會有醒目的提醒。
將單元測試放在首要地位的一種開發模式是TDD模式。TDD(Test Driven Development測試驅動開發)有三條嚴格的定律:
- 在編寫不能通過測試的單元測試前,不要編寫任何生產代碼。
- 只編寫恰好無法通過的單元測試,不能編譯也算不通過。
- 只編寫剛好足以通過當前失敗測試的生產代碼。
即使我們的團隊沒有完全採用TDD的開發模式,也可以借鑒這些定律來編寫我們自己的測試代碼。我們無需一次性編寫完全部的測試代碼,那沒有必要,這跟過度設計一樣,也不可能實現。事實上,我們應該逐步地編寫測試代碼,而且按如下步驟來編寫:
測試代碼->生產代碼->測試代碼
下面編寫一個單元測試的例子:
先編寫一個Add方法:
public class SampleClass { public int Add(int a, int b) { return a + b; } }
右鍵建立單元測試:
VS會自動為我們產生一個測試方法:
/// <summary> ///Add 的測試 ///</summary> [TestMethod()] public void AddTest() { SampleClass target = new SampleClass(); // TODO: 初始化為適當的值 int a = 0; // TODO: 初始化為適當的值 int b = 0; // TODO: 初始化為適當的值 int expected = 0; // TODO: 初始化為適當的值 int actual; actual = target.Add(a, b); Assert.AreEqual(expected, actual); Assert.Inconclusive("驗證此測試方法的正確性。"); }
將方法修改成我們需要的方法就可以了:
/// <summary> ///Add 的測試 ///</summary> [TestMethod()] public void AddTest() { SampleClass target = new SampleClass(); // TODO: 初始化為適當的值 int a = 1; // TODO: 初始化為適當的值 int b = 2; // TODO: 初始化為適當的值 int expected = 3; // TODO: 初始化為適當的值 int actual; actual = target.Add(a, b); Assert.AreEqual(expected, actual); Assert.Inconclusive("驗證此測試方法的正確性。"); }
VS這個可視化測試載入器太重量級了,導致開發的過程中運行測試代碼太繁瑣也太耗時。可以考慮用測試載入器TestDriven.NET,這裡不再介紹。
單元測試要注意一下幾點:
首先,單元測試不應引入任何人機互動的內容。如,測試過程中不應該彈出對話方塊,等待使用者輸入或確認。單元測試不應該是被阻滯的。
其次,多線程也不屬於單元測試範疇,單元測試應該是快速被執行的,而不是需要等待的。
最後,單元測試不應該跨應用程式定義域,例如,資料訪問或者遠程通訊屬於整合測試範疇,而不是單元測試。
轉自:《編寫高品質代碼改善C#程式的157個建議》陸敏技
【轉】編寫高品質代碼改善C#程式的157個建議——建議155:隨生產代碼一起提交單元測試代碼