繼上一篇的單元測試(1): 什麼是單元測試
單元測試的寫的好不好,影響執行測試結果的可信任度。
若測試莫名其妙就失敗,難以找到原因,或者錯誤卻不是由自己的受測試程式所造成,而是依賴的其他系統/服務的停止或失敗,測試的可信任度會愈來愈差,沒過多久,就沒有人相信測試的結果。到了最後,就連測試也不執行了。
所以,單元測試要寫好,就是要不相依於其他的服務/系統/程式。
以下舉個例子。
受測的程式
using System.IO;
namespace ClassLibrary1
{
public class Class1
{
///
/// 讀取檔案行數
///
public int CountFileLineNumber(string filePath)
{
return File.ReadAllLines(filePath).Length;
}
}
}
BAD單元測試
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 放到測試目錄一同進行測試,而程式碼在讀取的也會在執行目錄上找檔案。
這樣一來,該「相依於檔案系統」的依賴性就消除了,也就是就更像是「單元測試」了。