進度條

[C#][Unit Test] 06. 單元測試初始化與清除

本文利用C#與Visual Studio平台,來探討時下最夯的Unit Test。

作者: Toyo 更新日期:

此系列文轉自我們的好朋友Toyo大大網誌(原文連結),在Windows業界耕耘了多年,累積了不少實戰經驗。

此為他專門設計為新人的單元測試教學,進度條獲授權轉載。

原文標題:  【Unit Test】Day 6 - 單元測試初始化與清除

 

Demo檔案 : Git傳送門
請參照UnitTest_Day5的Branch

 

 

今天要來看看單元測試的初始化設定與清除

 

 

 

 

 

上圖是單元測試在執行時的生命週期,知道了這特性的時候我們就可以依據測試的需要來加入適當的初始化設定。

 

 

以下範例來說明執行順序
這邊準備了一個Static Class,裡面有個Get方法很簡單的回傳Now這個屬性值

public static class Demo
{
    public static int Now { get; set; }
    public static int Get()
    {
        return Now;
    }
}

 

然後為它建立單元測試

 

 

 

 

先加上一個TestHook的檔案

 

 

 

 

[TestClass]
public class TestHook
{
    [AssemblyInitialize]
    public static void AssemblyInit(TestContext context)
    {
        Console.WriteLine(string.Format("{0} - AssemblyInitialize", Demo.Get()));
        Demo.Now += 1;
    }
 
    [AssemblyCleanup]
    public static void AssemblyCleanUp()
    {
        Console.WriteLine(string.Format("{0} - AssemblyCleanup", Demo.Get()));
        Demo.Now += 1;
    }
}

 

 

接著撰寫DemoTests.cs

 

[TestClass]
public class DemoTests
{
    [ClassInitialize]
    public static void ClassInit(TestContext context)
    {
        Console.WriteLine(string.Format("{0} - ClassInitialize", Demo.Get()));
        Demo.Now += 1;
    }
 
    [TestInitialize]
    public void TestInit()
    {
        Console.WriteLine(string.Format("{0} - TestInitialize", Demo.Get()));
        Demo.Now += 1;
    }
 
    [TestMethod]
    public void GetTest()
    {
        Console.WriteLine(string.Format("{0} - Test1", Demo.Get()));
        Demo.Now += 1;
    }
 
    [TestCleanup]
    public void TestCleanUp()
    {
        Console.WriteLine(string.Format("{0} - TestCleanup", Demo.Get()));
        Demo.Now += 1;
    }
 
    [ClassCleanup]
    public static void ClassCleanUp()
    {
        Console.WriteLine(string.Format("{0} - ClassCleanup", Demo.Get()));
        Demo.Now += 1;
    }
}

 

 

這裡目標很間單,測試的內容不是重點,而是希望透過輸出來看到執行的順序

 

 

可能有人會注意到為何有些方法例如ClassCleanup是需要Static,
有些又需要帶入TestContext的參數?
這其實是規定,如果不按照規則撰寫的話,
執行單元測試時就會得到以下錯誤訊息


 

 

接著執行單元測試看看輸出,點擊下面的輸出按鈕

 

 

 

 

 

這樣看就很明顯知道順序了!!

 

 

讓我們加上第二個測試

 

[TestMethod]
public void GetTest2()
{
    Console.WriteLine(string.Format("{0} - Test2", Demo.Get()));
    Demo.Now += 1;
}

 

 

全部測試執行然後看看結果

 

 

 

 

 

可以發現TestInitializeTestCleanUp是每個測試在執行前/後都會執行一次的,而且要特別強調一下,每個單元測試執行的順序是不固定的,所以如果在單元測試中有些初始化的動作,切記不要依賴每個測試之間的順序關係,否則可能會不定時的產生錯誤,請把每個測試都當成是獨立且無相依關係!!

 

 

從這個範例也可以看得到一個結論,如果在測試中有用到Production CodeStatic的參數或屬性,請記得養成良好習慣,要在CleanUp的方法中恢復它的預設值,否則Static是共用的,如果其他測試有用到同一個Static屬性,而互相改來改去不初始化,就很可能發生單元測試時好時壞的問題,這是切身之痛請勿以身試法XDD

 

 

上一篇:[C#][Unit Test] 05. 透過InternalsVisibleTo來達成單元測試的外部注入

下一篇:[C#][Unit Test] 07. Assert

 

 


最後,如果你喜歡我們的文章,別忘了到我們的FB粉絲團按讚喔!!

Medium 0

Toyo

年過30在軟體業載浮載沉的工程師, 期望靠著一點一滴累積與努力, 讓自己墊起腳能勾到一點點的夢想