VS2010中的自動化測試(2)——單元測試

概述

在軟件開發過程中,我們可能會有很多的模塊,而每個模塊有可能又由許多函數組成。當我們的系統發生錯誤時,我們必須定位發生錯誤的模塊,然後精確到模塊中某個具體的函數中,而這工作往往又是非常浪費時間和生產效率的,如果系統越複雜,那麼定位錯誤的成本將越高。所以在每個函數集成進模塊時,必須通過嚴格的單元測試來驗證。

在VS2010中我們可以爲我們的函數自動生成單元測試,無論它是否是public或者的private的。所有用於單元測試的類和函數都被定義在Microsoft.VisualStudio.TestTools.UnitTesting這個命名空間中。

創建Unit Test

我們先創建一個被測試的類庫工程,名字叫TestLibrary,然後添加如下代碼:

複製代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestLibrary
{
    public class Class1
    {
        public double CalculateTotalPrice(double quantity)
        {
            double totalPrice;
            double unitPrice;
            
            unitPrice = 16.0;

            totalPrice = unitPrice * quantity;
            return totalPrice;
        }

        public void GetTotalPrice()
        {
            int qty = 5;
            double totalPrice = CalculateTotalPrice(qty);
            Console.WriteLine("總價: " + totalPrice);
        }

    }
}
複製代碼

然後我們在需要單元測試的函數上鼠標右鍵,如圖會有個Create Unit Tests選項。

Untitled

點擊該選項後,就會彈出如下窗口,該窗口會顯示出該工程和類中所有的函數,這裏我們可以選擇我們要進行單元測試的函數。

Capture

我們選擇CalculateTotalPrice和GetTotalPrice兩個函數,點擊OK,然後輸入測試工程的名字點Create。(我們可以在Output project選項中選擇一個以創建的工程或者創建一個新的測試工程)我們的單元測試代碼就自動創建好了,當然,這個自動創建的測試代碼並沒有完成的,而是爲我們的單元測試搭好了框架而已。自動生成的代碼如下:

複製代碼
using TestLibrary;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;

namespace TestProject1
{
    
    
    ///<summary>
    ///This is a test class for Class1Test and is intended
    ///to contain all Class1Test Unit Tests
    ///</summary>
    [TestClass()]
    public class Class1Test
    {


        private TestContext testContextInstance;

        ///<summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        ///<summary>
        ///A test for CalculateTotalPrice
        ///</summary>
        [TestMethod()]
        public void CalculateTotalPriceTest()
        {
            Class1 target = new Class1(); // TODO: Initialize to an appropriate value
            double quantity = 0F; // TODO: Initialize to an appropriate value
            double expected = 0F; // TODO: Initialize to an appropriate value
            double actual;
            actual = target.CalculateTotalPrice(quantity);
            Assert.AreEqual(expected, actual);
            Assert.Inconclusive("Verify the correctness of this test method.");
        }

        ///<summary>
        ///A test for GetTotalPrice
        ///</summary>
        [TestMethod()]
        public void GetTotalPriceTest()
        {
            Class1 target = new Class1(); // TODO: Initialize to an appropriate value
            target.GetTotalPrice();
            Assert.Inconclusive("A method that does not return a value cannot be verified.");
        }
    }
}
複製代碼

其實,我們可以在創建單元測試時適當控制自動生成的測試代碼,如圖我們點擊Setting按鈕。

Capture2

這時會彈出如下圖的窗口

Capture3

在該對話框中,我們可以對生成的測試文件、測試類以及測試方法自定義名稱。

  • Mark all test results Inconclusive by default:選中該複選框可爲每個測試方法提供 Assert.Inconclusive() 語句作爲佔位符 Assert。清除該複選框可消除佔位符 Assert。
  • Enable generation warnings:在測試函數創建中如果遇到任何的錯誤,代碼生成器會將這些錯誤信息以註釋的形式寫在生成的代碼中。
  • Globally qualify all types:這個選項是用來解決多個類可能有相同名字的函數問題,單元測試文件可能包含有多個類的測試函數,所以有可能會有同名的衝突,所以爲了區分開同名的函數,會在測試命名中添加namespaces。
  • Enable documentation comments:選中此複選框可爲每個測試方法提供佔位符註釋。清除該複選框可消除佔位符註釋。
  • Honor InternalsVisibleTo Attribute:選中該複選框可使標爲 Friend 或 Internal 的方法被視爲公共方法(推薦)。清除該複選框則需要使用專用訪問器測試這些方法。

此外還可以注意到自動生成的代碼中有一些被註釋的方法,這些方法我們可以選擇使用:

  1. [ClassInitialize()]標記的方法可在運行類中的第一個測試前運行代碼。
  2. [ClassCleanUp()]標記的方法可在運行完類中的所有測試後運行代碼。
  3. [TestInitialize()]標記的方法可在運行每個測試前運行代碼。
  4. [TestCleanUp()]標記的方法可在運行完每個測試後運行代碼。

Assert語句

Assert語句用來比較從方法返回來的值和期望值,然後返回pass或者fail的結果。如果在一個測試方法中有多個Assert的話,那麼這個測試方法要通過測試必須讓所有的Assert方法通過,不然,其中有一個fail,那麼這個Case就會fail。如果我們的單元測試中沒有任何的Assert語句,那麼它的結果始終是pass的。

Assert類有許多進行比較的方法,此外還有StringAssertsCollectionAssert類也可用於單元測試中,具體的我們可以參加MSDN上的介紹了。

下面我們修改一下CalculateTotalPriceTest()這段測試代碼,並將最後的Assert.Inconclusive註釋:

複製代碼
        [TestMethod()]
        public void CalculateTotalPriceTest()
        {
            Class1 target = new Class1(); 
            double quantity = 10F; 
            double expected = 160F; 
            double actual;
            actual = target.CalculateTotalPrice(quantity);
            Assert.AreEqual(expected, actual);
            //Assert.Inconclusive("Verify the correctness of this test method.");
        }
複製代碼

最後我們可以在該函數中,右鍵鼠標然後點擊Run Tests運行測試一下我們的代碼。我們就可以在Test Results窗口中看見我們運行的結果。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章