繼上一篇的單元測試(1): 什麼是單元測試
單元測試的寫的好不好,影響執行測試結果的可信任度。
若測試莫名其妙就失敗,難以找到原因,或者錯誤卻不是由自己的受測試程式所造成,而是依賴的其他系統/服務的停止或失敗,測試的可信任度會愈來愈差,沒過多久,就沒有人相信測試的結果。到了最後,就連測試也不執行了。
所以,單元測試要寫好,就是要不相依於其他的服務/系統/程式。
以下舉個例子。
受測的程式using System.IO; namespace ClassLibrary1 { public class Class1 { ///BAD單元測試/// 讀取檔案行數 /// public int CountFileLineNumber(string filePath) { return File.ReadAllLines(filePath).Length; } } }
using ClassLibrary1; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace TestProject1 { [TestClass()] public class Class1Test { [TestMethod()] public void CountFileLineNumberTest() { Class1 target = new Class1(); int actual =target.CountFileLineNumber(@"d:\temp\aaa.txt"); Assert.AreEqual(4, actual); } } }以上的例子是可以正常測試的。那到底什麼地方不好呢?
首先,該測試通常受到版本控管。當別人在他的電腦取得測試後,一旦執行該測試後,通常會失敗。原因:找不到 d:\temp\aaa.txt。
因為該測試必須有 aaa.txt 的輔助才能進行,如果沒有將該檔案一起放到 source control,其他同事進行測試時就會失敗。
再者,別人的電腦, d drive可能是光碟,也可能沒有對應的邏輯磁碟。
這就是「相依於檔案系統」造成的問題。
該怎麼改呢?首先將aaa.txt 加到測試專案中,並且將Copy to Output Directory 的值設為 Copy always。這樣一來,該測試檔案就會跟著專案一起了。
再來,將測試程式修改成下方。
using ClassLibrary1; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace TestProject1 { [TestClass()] public class Class1Test { [TestMethod()] [DeploymentItem("aaa.txt")] <!-- 多這一行 --> public void CountFileLineNumberTest() { Class1 target = new Class1(); int actual =target.CountFileLineNumber(@"aaa.txt"); <!-- 修改這一行 --> Assert.AreEqual(4, actual); } } }
DeploymentItem 指名要將 aaa.txt 放到測試目錄一同進行測試,而程式碼在讀取的也會在執行目錄上找檔案。
這樣一來,該「相依於檔案系統」的依賴性就消除了,也就是就更像是「單元測試」了。