2009年8月28日 星期五

單元測試(2): 單元測試的好與壞

繼上一篇的單元測試(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。這樣一來,該測試檔案就會跟著專案一起了。

image

再來,將測試程式修改成下方。

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 放到測試目錄一同進行測試,而程式碼在讀取的也會在執行目錄上找檔案。

這樣一來,該「相依於檔案系統」的依賴性就消除了,也就是就更像是「單元測試」了。

沒有留言:

Share with Facebook