進行UI介面的單元測試 實作與工具篇 (OneNet魔力小子)

進行UI介面的單元測試 實作與工具篇 (OneNet魔力小子)

         本篇是主要在介紹 UI(使用者介面)的單元測試,在寫單元測試中最讓人頭痛的就是 UI層很難進行測試,尤其是UI層與邏輯層的程式耦合度很高的程式專案,而 NUnitForms 就是用來解決這個問題的良好工具,NUnitForms是作為NUnit的擴展,他主要的用途是專為Windows Forms應用程式的表單測試而設計的。

        NUnitForms 可以跟 NUnit(單元測試)進行良好的配合機制,在撰寫NUnit單元測試的程式碼中,可以利用NUnitForms 的來跟Windows Form進行互動,過程中不需要再經由User(使用者)進行人工操作,因此可以用來模擬使用者操作UI的輸入,來進行接受性的單元測試,NUnit目前可以支援的控制項元素包含需多,如:Buttons, CheckBoxes, ComboBoxes, Labels, ListBoxes, RadioButtons, TabControls, TextBoxes, TreeViews, Context Menus, Forms, MenuItems, Modal Forms, Modal MessageBoxes, and the Mouse 。
官方網站:http://nunitforms.sourceforge.net/index.html

       下載NUnitForms,並安裝完成後,就可以新增一個程式類別專案,對NUnitForm.dll的參考引用,步驟如下:
先新增一個類別專案
001

在專案的參考節點上按右鍵進行參考引用 NUnitForm.dll
002 
003

引用NUnitForms.dll檔後,在命名空間添加
using NUnit.Extensions;
using NUnit.Extensions.Forms;
004 

上述步驟完成後,接下要在單元測試程式碼(NUnit)中針對將要進行測試的Windows Form(表單),需要執行類似下列語法來初始化。
Form1 form = new Fom1();
//進行Form.Show()來顯示啟用表單
form.Show();

     這邊有個觀念需要先特別說明,在NUnitForms框架中,已經實作出很多測試表單(Windows Form)過程中,可以模擬的Control,因此在寫單元測試中,可以根據實際需要模擬的Control,進行宣告物件實體,例如要模擬表單的TextBox,就可以新建一個Object 為 TextBoxTester,模擬Button按鈕,就可以新建立一個 ButtonTester,仔細觀察你會發現,結尾都是Tester居多,而這些模擬的Control都是延自一個基類為 ControlTester。而每個 ***Tester都有提供一些方法與屬性,來供程式呼叫與使用,以下特別撰寫這幾個範例:

ex1:
//使用 ControlTester 來存取 TestBox 控制項的屬性
ControlTester textBoxTest = new ControlTester("textBox1") ;  // textBox1為Windows Form表單上的TextBox控制項ID

ex2:
//使用 ControlTester 來存取 Button 控制項的屬性
ControlTester buttonTest = new ControlTester("button1");    // button1為Windows Form表單上的Button控制項ID

ex3:
// 抓取某個 Form (在此為form1) 上的 button1 控制項
// 如果忽略掉 form1 參數,則NUnitForm將搜尋所有以呼叫 Form.Show() 的表單
ControlTester buttonByFormIdTest = new ControlTester("button1", "form1");


    根據上述語法,將可以順利取得要測試的Control項目,以下根據上述在繼續寫幾個範例,來讀取控制項的屬性或呼叫歸屬方法:

ex1:  
//使用 ControlTester 來存取 TestBox 控制項的屬性
ControlTester textBoxTest = new ControlTester("textBox1") ;  // textBox1為Windows Form表單上的TextBox控制項ID
//讀取 TextBox.Text , 並列印出
System.Console.Out.WriteLine(textBoxTest["Text"].ToString());

ex2:
//使用 ControlTester 來存取 Button 控制項的屬性
// button1為Windows Form表單上的Button控制項ID
ControlTester buttonTest = new ControlTester("button1");   
//觸發Button.Click()方法
buttonTest.FireEvent("Click", new EventArgs());

ex3:
//利用 ButtonTester 來測試 Button 作法
ButtonTester buttonTest2 = new ButtonTester("button1");
//引用Button.Click() 方法
buttonTest2.Click();

[案例分享]
      接下來,筆者將完成一個實作案例,來完成NUnit與NUnitForms的測試案例,案例將模擬有一個Windows Form表單,而這個表單擁有一個Button控制項、一個TestBox控制項、以及一個Label控制項,然後在使用NUnit(單元測試)與NUnitForms,實作出模擬預期使用者操作Form表單後,將出現的值來進行測試案例。 (本篇假設讀者已知NUnit單元測試的實作技巧)
     

       現在在專案裡新增一個Windows Form,並取名為form1

005







 

 

 

 

 

 

在form1,從工具項拖拉Button、TextBox、Label控制項到 form1 裡
006

在button1.Click() (雙點擊button1),撰寫下列語法:

   1: private void button1_Click(object sender, EventArgs e)
   2:        {
   3:            //TextBox輸入字串顯示至Label
   4:            this.label1.Text = this.textBox1.Text;
   5:        }

在專案裡,在新增一個Class,並命名為 NUnitFormsTest.cs,如下圖:

007 

008

在專案裡參考引用 unit.framework.dll 與 NUnitForms.dll
 009

010

在NUnitFormsTest.cs 引用下列命名空間

using NUnit.Framework;
using NUnit.Extensions.Forms;

撰寫下列整合NUnitForms程式碼

   1: // [TestFixture] 標示此 Class 為 NUnit 測試用途
   2:    [TestFixture] 
   3:    public  class NUnitFormsTest
   4:    {
   5:  
   6:        // [Test] 標示此 Method 為 NUnit的測試方法
   7:        [Test]
   8:        public void Test01_ButtonClick()
   9:        {
  10:            //new form1 object and Show form1
  11:            form1 form = new form1();
  12:            form.Show();
  13:            
  14:            TextBoxTester txtTest = new TextBoxTester("textBox1");
  15:            //模擬使用者 KeyIn 值
  16:            txtTest["Text"] = "輸入值測試";
  17:  
  18:            ButtonTester btnTest = new ButtonTester("button1");
  19:            //呼叫Button.Click()
  20:            btnTest.Click();
  21:  
  22:            LabelTester lblTest = new LabelTester("label1");
  23:  
  24:            //進行測試
  25:            Assert.AreEqual("輸入值測試", lblTest["Text"].ToString(), "Error Value Not Mapping..");
  26:  
  27:        }       
  28:    }

執行NUnitGUI,將可以看到執行結果,是否正確
011

在此省略掉NUnit的技巧,如果改天還有時間,我將會補齊這塊NUnit測試技巧。