1. TDD的簡介
2.NUnit的介紹
2.1 NUnit的介紹
圖2 NUnit運行的另外一個效果
- 綠色 描述目前所執行的測試都通過
- 黃色 意味某些測試忽略,但是這裏沒有失敗
- 紅色 表示有失敗
- 狀態.說明了現在運行測試的狀態。當所有測試完成時,狀態變爲Completed.運行測試中,狀態是Running: <test-name> (<test-name>是正在運行的測試名稱)。
- Test Cases說明加載的程序集中測試案例的總個數。這也是測試樹裏葉子節點的個數。
- Tests Run 已經完成的測試個數。
- Failures 到目前爲止,所有測試中失敗的個數.
- Time 顯示運行測試時間(以秒計)
- New Project允許你創建一個新工程。工程是一個測試程序集的集合。這種機制讓你組織多個測試程序集,並把他們作爲一個組對待。
- Open 加載一個新的測試程序集,或一個以前保存的NUnit工程文件。
- Close關閉現在加載的測試程序集或現在加載的NUnit工程。
- Save 保存現在的Nunit工程到一個文件。如果正工作單個程序集,本菜單項允許你創建一個新的NUnit工程,並把它保存在文件裏。
- Save As允許你將現有NUnit工程作爲一個文件保存。
- Reload 強制重載現有測試程序集或NUnit工程。NUnit-Gui自動監測現加載的測試程序集的變化。
- Recent Files 說明5個最近在NUnit中加載的測試程序集或NUnit工程(這個列表在Windows註冊表,由每個用戶維護,因此如果你共享你的PC,你僅看到你的測試)。最近程序集的數量可以使用Options菜單項修改,可以訪問Tool主菜單。
- Exit退出。
- View菜單有以下內容:
- Expand一層層擴展現在樹中所選節點
- Collapse 摺疊現在樹中選擇的節點
- Expand All遞歸擴展樹中所選節點後的所有節點
- Collapse All遞歸摺疊樹中所選節點後的所有節點
- Expand Fixtures擴展樹中所有代表測試fixture的節點。
- Collapse Fixtures 摺疊樹中所有代表測試fixture的節點。
- Properties 顯示樹中現所選節點的屬性。
- Tools 菜單由這些項:
- Save Results as XML作爲一XML文件保存運行測試的結果。
- Options讓你定製NUnit的行爲。
- Errors and Failures 窗口顯示失敗的測試。在我們的例子裏,這個窗口是空。
- Tests Not Run 窗口顯示沒有得到執行的測試。
- Console.Error 窗口顯示運行測試產生的錯誤消息。這些此消息是應用程序代碼使用Console.Error輸出流可以輸出的。
- Console.Out窗口顯示運行測試打印到Console.Error輸出流的文本消息。
2.2 一些常用屬性
- Test Fixture
- Test
TestFixtureAttribute
- 必須是Public,否則NUnit看不到它的存在.
- 它必須有一個缺省的構造函數,否則是NUnit不會構造它.
- 構造函數應該沒有任何副作用,因爲NUnit在運行時經常會構造這個類多次,如果要是構造函數要什麼副作用的話,那不是亂了.
1 using System;
2 using NUnit.Framework;
3 namespace MyTest.Tests
4{
5
6 [TestFixture]
7 public class PriceFixture
8 {
9 //
10 }
11}
12
TestAttribute
public void MethodName()
1using System;
2using NUnit.Framework;
3
4namespace MyTest.Tests
5{
6 [TestFixture]
7 public class SuccessTests
8 {
9 [Test] public void Test1()
10 { /* */ }
11 }
12}
13
14
一般來說,有了上面兩個屬性,你可以做基本的事情了.
另外,我們再對如何進行比較做一個描述。
在NUnit中,用Assert(斷言)進行比較,Assert是一個類,它包括以下方法:AreEqual,AreSame,Equals, Fail,Ignore,IsFalse,IsNotNull,具體請參看NUnit的文檔。
3.如何在.NET中應用NUnit
第1步.爲測試代碼創建一個Visual Studio工程。
圖 4-1: 創建第一個NUnit工程
第2步.增加一個NUnit框架引用
圖 4-2: 增加一個 NUnit.framework.dll 引用到工程
第3步.爲工程加一個類.
2using NUnit.Framework;
3
4namespace NUnitQuickStart
5{
6 [TestFixture]
7 public class NumersFixture
8 {
9 [Test]
10 public void AddTwoNumbers()
11 {
12 int a=1;
13 int b=2;
14 int sum=a+b;
15 Assert.AreEqual(sum,3);
16 }
17 }
18}
19
第4步.建立你的Visual Studio 工程,使用NUnit-Gui測試
第5步.編譯運行測試.
圖 4-4: 測試程序集的測試在 NUnit-Gui中的視圖
4.其他的一些核心概念
SetUp/TearDown 屬性
2using NUnit.Framework;
3
4namespace NUnitQuickStart
5{
6 [TestFixture]
7 public class NumersFixture
8 {
9 [Test]
10 public void AddTwoNumbers()
11 {
12 int a=1;
13 int b=2;
14 int sum=a+b;
15 Assert.AreEqual(sum,3);
16 }
17 [Test]
18 public void MultiplyTwoNumbers()
19 {
20 int a = 1;
21 int b = 2;
22 int product = a * b;
23 Assert.AreEqual(2, product);
24 }
25
26 }
27}
28
2using NUnit.Framework;
3
4namespace NUnitQuickStart
5{
6 [TestFixture]
7 public class NumersFixture
8 {
9 private int a;
10 private int b;
11 [SetUp]
12 public void InitializeOperands()
13 {
14 a = 1;
15 b = 2;
16 }
17
18 [Test]
19 public void AddTwoNumbers()
20 {
21 int sum=a+b;
22 Assert.AreEqual(sum,3);
23 }
24 [Test]
25 public void MultiplyTwoNumbers()
26 {
27 int product = a * b;
28 Assert.AreEqual(2, product);
29 }
30
31 }
32}
33
這樣NUnit將在執行每個測試前執行標記SetUp屬性的方法.在本例中就是執行InitializeOperands()方法.記住,這裏這個方法必須爲public,不然就會有以下錯誤:Invalid Setup or TearDown method signature
ExpectedException
1[Test]
2[ExpectedException(typeof(DivideByZeroException))]
3public void DivideByZero()
4{
5 int zero = 0;
6 int infinity = a/zero;
7 Assert.Fail("Should have gotten an exception");
8}
9
Ignore 屬性
1[Test]
2[Ignore("Multiplication is ignored")]
3public void MultiplyTwoNumbers()
4{
5 int product = a * b;
6 Assert.AreEqual(2, product);
7}
圖 5-1: 在一個程序員測試中使用 Ignore屬性
TestFixtureSetUp/TestFixtureTearDown
1using NUnit.Framework;
2
3[TestFixture]
4public class DatabaseFixture
5{
6 [TestFixtureSetUp]
7 public void OpenConnection()
8 {
9 //open the connection to the database
10 }
11
12 [TestFixtureTearDown]
13 public void CloseConnection()
14 {
15 //close the connection to the database
16 }
17
18 [SetUp]
19 public void CreateDatabaseObjects()
20 {
21 //insert the records into the database table
22 }
23
24 [TearDown]
25 public void DeleteDatabaseObjects()
26 {
27 //remove the inserted records from the database table
28 }
29
30 [Test]
31 public void ReadOneObject()
32 {
33 //load one record using the open database connection
34 }
35
36 [Test]
37 public void ReadManyObjects()
38 {
39 //load many records using the open database connection
40 }
41}
42
43
Test Suite
1namespace NUnit.Tests
2{
3using System;
4 using NUnit.Framework;
5
6
7
8 public class AllTests
9 {
10 [Suite]
11 public static TestSuite Suite
12 {
13 get
14 {
15 TestSuite suite = new TestSuite("All Tests");
16 suite.Add(new OneTestCase());
17 suite.Add(new Assemblies.AssemblyTests());
18 suite.Add(new AssertionTest());
19 return suite;
20 }
21 }
22 }
23}
24
Category屬性
2{
3using System;
4 using NUnit.Framework;
5
6
7
8 public class AllTests
9 {
10 [Suite]
11 public static TestSuite Suite
12 {
13 get
14 {
15 TestSuite suite = new TestSuite("All Tests");
16 suite.Add(new OneTestCase());
17 suite.Add(new Assemblies.AssemblyTests());
18 suite.Add(new AssertionTest());
19 return suite;
20 }
21 }
22 }
23}
24
1using System;
2using NUnit.Framework;
3
4namespace NUnitQuickStart
5{
6 [TestFixture]
7 public class NumersFixture
8 {
9 private int a;
10 private int b;
11 [SetUp]
12 public void InitializeOperands()
13 {
14 a = 1;
15 b = 2;
16 }
17
18 [Test]
19 [Category("Numbers")]
20 public void AddTwoNumbers()
21 {
22 int sum=a+b;
23 Assert.AreEqual(sum,3);
24 }
25
26 [Test]
27 [Category("Exception")]
28 [ExpectedException(typeof(DivideByZeroException))]
29 public void DivideByZero()
30 {
31 int zero = 0;
32 int infinity = a/zero;
33 Assert.Fail("Should have gotten an exception");
34 }
35 [Test]
36 [Ignore("Multiplication is ignored")]
37 [Category("Numbers")]
38 public void MultiplyTwoNumbers()
39 {
40 int product = a * b;
41 Assert.AreEqual(2, product);
42 }
43
44 }
45
NUnit-GUI界面如圖5-2:
圖5-2:使用Catagories屬性的界面
Explicit屬性
2 [Test,Explicit]
3 [Category("Exception")]
4 [ExpectedException(typeof(DivideByZeroException))]
5 public void DivideByZero()
6 {
7 int zero = 0;
8 int infinity = a/zero;
9 Assert.Fail("Should have gotten an exception");
10 }
11
Expected Exception屬性
2[ExpectedException(typeofInvalidOperationException))]
3public void ExpectAnException()
4 {
5 int zero = 0;
6 int infinity = a/zero;
7 Assert.Fail("Should have gotten an exception");
8
9 }
10
5 . 測試生命週期合約
1using System;
2using NUnit.Framework;
3[TestFixture]
4public class LifeCycleContractFixture
5{
6 [TestFixtureSetUp]
7 public void FixtureSetUp()
8 {
9 Console.Out.WriteLine("FixtureSetUp");
10 }
11
12 [TestFixtureTearDown]
13 public void FixtureTearDown()
14 {
15 Console.Out.WriteLine("FixtureTearDown");
16 }
17
18 [SetUp]
19 public void SetUp()
20 {
21 Console.Out.WriteLine("SetUp");
22 }
23
24 [TearDown]
25 public void TearDown()
26 {
27 Console.Out.WriteLine("TearDown");
28 }
29
30 [Test]
31 public void Test1()
32 {
33 Console.Out.WriteLine("Test 1");
34 }
35
36 [Test]
37 public void Test2()
38 {
39 Console.Out.WriteLine("Test 2");
40 }
41
42}
43
44
FixtureSetUp
SetUp
Test 1
TearDown
SetUp
Test 2
TearDown
FixtureTearDown
6) NUnit中文文檔:http://www.36sign.com/nunit