首页 > 代码库 > 走进 .Net 单元测试

走进 .Net 单元测试

走进 .Net 单元测试

Intro

“不会写单元测试的程序员不是合格的程序员,不写单元测试的程序员不是优秀程序员。”

—— 一只想要成为一个优秀程序员的渣逼程序猿。

那么问题来了,什么是单元测试,如何做单元测试。

单元测试定义

按照维基百科上的说法,单元测试(Unit Testing)又称为模块测试, 是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。 程序单元是应用的最小可测试部件。在面向对象编程中,最小单元就是方法,包括基类、抽象类、或者派生类(子类)中的方法。 按照通俗的理解,一个单元测试判断某个特定场条件下某个特定方法的行为,如斐波那契数列算法,冒泡排序算法。

单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。 对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义, 如C语言中单元指一个函数,Java里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等。 总的来说,单元就是人为规定的最小的被测功能模块。 单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。

—— 百度百科 http://baike.baidu.com/view/106237.htm

进行单元测试的好处

  1. 它是一种验证行为

    程序中的每一项功能都是测试来验证它的正确性。

  2. 它是一种设计行为

    编写单元测试将使我们从调用者观察、思考。 特别是先写测试(test-first),迫使我们把程序设计成易于调用和可测试的,有利于程序的解耦和模块化。

  3. 它是一种编写文档的行为

    单元测试是一种无价的文档,它是展示函数或类如何使用的最佳文档。这份文档是可编译、可运行的,并且它保持最新,永远与代码同步。

  4. 它具有回归性

    自动化的单元测试避免了代码出现回归,编写完成之后,可以随时随地的快速运行测试。

  5. 高效

    自动化的单元测试节省了开发上调试BUG的时间,绝大多数BUG可以通过单元测试测试出来,并且可以减少测试人员的测试时间。有时候通过写单元测试能够更好的完善自己程序的逻辑,让程序变得更加美好。

    —— 单元测试的优点 http://jingyan.baidu.com/article/d713063522ab4e13fdf47533.html

单元测试的原则:

  • 可重复运行的
  • 持续长期有效,并且返回一致的结果
  • 在内存中运行,没有外部依赖组件(比如说真实的数据库,真实的文件存储等)
  • 快速返回结果
  • 一个测试方法只测试一个问题

VS单元测试 【MsTest】使用

VS单元测试的主要类:Assert、StringAssert、CollectionAssert,具体可参照 MSDN介绍

有些时候我们需要对测试的方法用到的数据或配置进行初始化,有几个特殊的测试方法。

如果需要针对测试中的所有虚拟用户迭代仅执行一次初始化操作,请使用 TestInitializeAttribute。

初始化方法的运行顺序如下:

  1. 用 AssemblyInitializeAttribute 标记的方法。
  2. 用 ClassInitializeAttribute 特性标记的方法。
  3. 用 TestInitializeAttribute 特性标记的方法。
  4. 用 TestMethodAttribute 特性标记的方法。

单元测试 使用示例 

技术分享
  1 using Microsoft.VisualStudio.TestTools.UnitTesting;
  2 
  3 namespace ConsoleApplication1Test
  4 {
  5     [TestClass]
  6     public class MainTest
  7     {
  8         #region TestFail
  9 
 10         [TestMethod]
 11         public void TestFail0()
 12         {
 13             Assert.Fail();
 14         }
 15 
 16         [TestMethod]
 17         public void TestFail1()
 18         {
 19             Assert.Fail("Test is fail");
 20         }
 21 
 22         [TestMethod]
 23         public void TestFail2()
 24         {
 25             Assert.Fail("Test3 is fail,{0}", "hahaha");
 26         }
 27         #endregion
 28 
 29         #region TestInconclusive 忽略
 30         [TestMethod]
 31         public void TestInconclusive0()
 32         {
 33             Assert.Inconclusive();
 34         }
 35 
 36         [TestMethod]
 37         public void TestInconclusive1()
 38         {
 39             Assert.Inconclusive("Inconclusive");
 40         }
 41 
 42         [TestMethod]
 43         public void TestInconclusive2()
 44         {
 45             Assert.Inconclusive("Inconclusive,{0}", "hehehe");
 46         }
 47         #endregion
 48 
 49         #region LogicTest
 50 
 51         #region Null
 52         [TestMethod]
 53         public void IsNullTest()
 54         {
 55             Assert.IsNull(null);
 56         }
 57 
 58         [TestMethod]
 59         public void IsNotNullTest()
 60         {
 61             Assert.IsNotNull(1);
 62         } 
 63         #endregion
 64 
 65         #region True || False
 66         [TestMethod]
 67         public void IsTrueTest()
 68         {
 69             Assert.IsTrue(1 == 1);
 70         }
 71 
 72         [TestMethod]
 73         public void IsFalseTest()
 74         {
 75             Assert.IsFalse(1 > 2);
 76         } 
 77         #endregion
 78 
 79         #region AreSame
 80         [TestMethod]
 81         public void AreSameTest()
 82         {
 83             //不要向 AreSame() 传递值类型的值,因为他们转换为 Object 后永久不会相等,值类型的值比较请使用 AreEqual()
 84             Assert.AreSame(1, 1);
 85         }
 86 
 87         [TestMethod]
 88         public void AreSameTest1()
 89         {
 90             object obj = new object(), obj1 = obj;
 91             Assert.AreSame(obj, obj1, "same");
 92         }
 93 
 94         [TestMethod]
 95         public void StringAreSameTest0()
 96         {
 97             string str1 = "hello", str2 = "hello";
 98             Assert.AreSame(str1, str2);
 99         }
100 
101         [TestMethod]
102         public void StringAreSameTest1()
103         {
104             string str1 = "hello", str2 = "Hello";
105             Assert.AreSame(str1, str2);
106         }
107 
108         [TestMethod]
109         public void AreNotSameTest()
110         {
111             object obj = new object(), obj1 = new object();
112             Assert.AreNotSame(obj, obj1);
113         } 
114         #endregion
115 
116         #region AreEqual
117         [TestMethod]
118         public void AreEqualTest()
119         {
120             Assert.AreEqual(1, 1);
121         }
122 
123         [TestMethod]
124         public void AreNotEqualTest()
125         {
126             Assert.AreNotEqual(1, 2);
127         }
128 
129         [TestMethod]
130         public void AreEqualTest1()
131         {
132             object obj = new object(), obj1 = obj;
133             Assert.AreEqual(obj, obj1);
134         }
135 
136         [TestMethod]
137         public void AreNotEqualTest1()
138         {
139             object obj = new object(), obj1 = new object();
140             Assert.AreNotEqual(obj, obj1);
141         }
142 
143         [TestMethod]
144         public void AreEqualTest2()
145         {
146             object obj = new object(), obj1 = new object();
147             Assert.AreEqual(obj, obj1);
148             // Assert.Equals()不用于断言,请使用 Assert.AreEquals() 或 Assert.AreNotEquals()
149             //Assert.Equals(obj, obj1);
150         }
151 
152         [TestMethod]
153         public void StringAreEqualTest0()
154         {
155             string str = "hello", str1 = "hello";
156             Assert.AreEqual(str, str1);
157         }
158 
159         [TestMethod]
160         public void StringAreEqualTest1()
161         {
162             string str = "hello", str1 = "Hello";
163             Assert.AreEqual(str, str1, true);
164         } 
165         #endregion
166 
167         #region IsInstanceOfType
168 
169         [TestMethod]
170         public void IsInstanceOfTypeTest()
171         {
172             B b = new B();
173             Assert.IsInstanceOfType(b, typeof(A));
174         }
175 
176         [TestMethod]
177         public void IsNotInstanceOfTypeTest()
178         {
179             A a = new A();
180             Assert.IsNotInstanceOfType(a, typeof(B));
181         }
182         #endregion
183 
184         #endregion
185 
186         #region 测试初始化和清理
187         [AssemblyInitialize()]
188         public static void AssemblyInit(TestContext context)
189         {
190             System.Console.WriteLine("AssemblyInit " + context.TestName);
191         }
192 
193         [ClassInitialize()]
194         public static void ClassInit(TestContext context)
195         {
196             System.Console.WriteLine("ClassInit " + context.TestName);
197         }
198 
199         [TestInitialize]
200         public void Initialize()
201         {
202             System.Console.WriteLine("TestMethodInit");
203         }
204 
205         [TestCleanup]
206         public void Cleanup()
207         {
208             System.Console.WriteLine("TestMethodCleanup");
209         }
210 
211         [ClassCleanup]
212         public static void ClassCleanup()
213         {
214             System.Console.WriteLine("ClassCleanup");
215         }
216 
217         [AssemblyCleanup]
218         public static void AssemblyCleanup()
219         {
220             System.Console.WriteLine("AssemblyCleanup");
221         } 
222         #endregion
223     }
224 
225     public class A { }
226 
227     public class B : A { }
228 
229 }
Ms Test单元测试

MsTest 和 Nunit区别

MS Test框架是Visual Studio自带的测试框架,可以通过新建一个Unit Test Project工程, 也可以建一个Class Libary,然后添加对Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll的引用。 然后就是创建测试用例,进行测试即可。

NUnit Test框架是一个xUnit家族种的第4个主打产品,完全由C#语言来编写,支持所有的.Net语言。 使用NUnit框架,我们需要下载安装包,安装后使用独立客户端进行使用。使用方法与MS Test类似

有一些是NUnit中的,但是MS Test框架中是没有的: - Assert.IsNaN - Assert.IsEmpty - Assert.IsNotEmpty - Assert.Greater - Assert.GreaterOrEqual - Assert.Less - Assert.LessOrEqual - Assert.IsAssignableFrom - Assert.IsNotAssignableFrom - Assert.Igore - CollectionAssert.IsEmpty - CollectionAssert.IsNotEmpty - StringAssert.AreEqualIgnoringCase - StringAssert.IsMatch - FileAssert.AreEqual - FileAssert.AreNotEqual

同时支持两种测试框架

可以通过宏判断来同时支持这两个框架,在测试前添加以下代码: 

 1 #if !NUNIT 
 2 using Microsoft.VisualStudio.TestTools.UnitTesting; 
 3 using Category = Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute; 
 4 #else 
 5 using NUnit.Framework; 
 6 using TestClass = NUnit.Framework.TestFixtureAttribute; 
 7 using TestMethod = NUnit.Framework.TestAttribute; 
 8 using TestInitialize = NUnit.Framework.SetUpAttribute; 
 9 using TestCleanup = NUnit.Framework.TearDownAttribute; 
10 using TestContext = System.Object; 
11 using ClassCleanup = NUnit.Framework.TestFixtureTearDownAttribute; 
12 using ClassInitialize = NUnit.Framework.TestFixtureSetUpAttribute; 
13 #endif

 

Nunit测试使用示例

技术分享
  1 #region NUNIT
  2 
  3     /// <summary>
  4     /// This test fixture attempts to exercise all the syntactic
  5     /// variations of Assert without getting into failures, errors 
  6     /// or corner cases.Thus, some of the tests may be duplicated 
  7     /// in other fixtures.
  8     /// 
  9     /// Each test performs the same operations using the classic
 10     /// syntax(if available) and the new syntax in both the
 11     /// helper-based and inherited forms.
 12     /// 
 13     /// This Fixture will eventually be duplicated in other
 14     /// supported languages. 
 15     /// </summary>
 16     [TestFixture]
 17     public class AssertSyntaxTests : AssertionHelper
 18     {
 19         #region Simple Constraint Tests
 20         [Test]
 21         public void IsNull()
 22         {
 23             object nada = null;
 24 
 25             // Classic syntax
 26             Assert.IsNull(nada);
 27 
 28             // Constraint Syntax
 29             Assert.That(nada, Is.Null);
 30 
 31             // Inherited syntax
 32             Expect(nada, Null);
 33         }
 34 
 35         [Test]
 36         public void IsNotNull()
 37         {
 38             // Classic syntax
 39             Assert.IsNotNull(42);
 40 
 41             // Constraint Syntax
 42             Assert.That(42, Is.Not.Null);
 43 
 44             // Inherited syntax
 45             Expect(42, Not.Null);
 46         }
 47 
 48         [Test]
 49         public void IsTrue()
 50         {
 51             // Classic syntax
 52             Assert.IsTrue(2 + 2 == 4);
 53 
 54             // Constraint Syntax
 55             Assert.That(2 + 2 == 4, Is.True);
 56             Assert.That(2 + 2 == 4);
 57 
 58             // Inherited syntax
 59             Expect(2 + 2 == 4, True);
 60             Expect(2 + 2 == 4);
 61         }
 62 
 63         [Test]
 64         public void IsFalse()
 65         {
 66             // Classic syntax
 67             Assert.IsFalse(2 + 2 == 5);
 68 
 69             // Constraint Syntax
 70             Assert.That(2 + 2 == 5, Is.False);
 71 
 72             // Inherited syntax
 73             Expect(2 + 2 == 5, False);
 74         }
 75 
 76         [Test]
 77         public void IsNaN()
 78         {
 79             double d = double.NaN;
 80             float f = float.NaN;
 81 
 82             // Classic syntax
 83             Assert.IsNaN(d);
 84             Assert.IsNaN(f);
 85 
 86             // Constraint Syntax
 87             Assert.That(d, Is.NaN);
 88             Assert.That(f, Is.NaN);
 89 
 90             // Inherited syntax
 91             Expect(d, NaN);
 92             Expect(f, NaN);
 93         }
 94 
 95         [Test]
 96         public void EmptyStringTests()
 97         {
 98             // Classic syntax
 99             Assert.IsEmpty("");
100             Assert.IsNotEmpty("Hello!");
101 
102             // Constraint Syntax
103             Assert.That("", Is.Empty);
104             Assert.That("Hello!", Is.Not.Empty);
105 
106             // Inherited syntax
107             Expect("", Empty);
108             Expect("Hello!", Not.Empty);
109         }
110 
111         [Test]
112         public void EmptyCollectionTests()
113         {
114             // Classic syntax
115             Assert.IsEmpty(new bool[0]);
116             Assert.IsNotEmpty(new int[] { 1, 2, 3 });
117 
118             // Constraint Syntax
119             Assert.That(new bool[0], Is.Empty);
120             Assert.That(new int[] { 1, 2, 3 }, Is.Not.Empty);
121 
122             // Inherited syntax
123             Expect(new bool[0], Empty);
124             Expect(new int[] { 1, 2, 3 }, Not.Empty);
125         }
126         #endregion
127 
128         #region TypeConstraint Tests
129         [Test]
130         public void ExactTypeTests()
131         {
132             // Classic syntax workarounds
133             Assert.AreEqual(typeof(string), "Hello".GetType());
134             Assert.AreEqual("System.String", "Hello".GetType().FullName);
135             Assert.AreNotEqual(typeof(int), "Hello".GetType());
136             Assert.AreNotEqual("System.Int32", "Hello".GetType().FullName);
137 
138             // Constraint Syntax
139             Assert.That("Hello", Is.TypeOf(typeof(string)));
140             Assert.That("Hello", Is.Not.TypeOf(typeof(int)));
141 
142             // Inherited syntax
143             Expect("Hello", TypeOf(typeof(string)));
144             Expect("Hello", Not.TypeOf(typeof(int)));
145         }
146 
147         [Test]
148         public void InstanceOfTests()
149         {
150             // Classic syntax
151             Assert.IsInstanceOf(typeof(string), "Hello");
152             Assert.IsNotInstanceOf(typeof(string), 5);
153 
154             // Constraint Syntax
155             Assert.That("Hello", Is.InstanceOf(typeof(string)));
156             Assert.That(5, Is.Not.InstanceOf(typeof(string)));
157 
158             // Inherited syntax
159             Expect("Hello", InstanceOf(typeof(string)));
160             Expect(5, Not.InstanceOf(typeof(string)));
161         }
162 
163         [Test]
164         public void AssignableFromTypeTests()
165         {
166             // Classic syntax
167             Assert.IsAssignableFrom(typeof(string), "Hello");
168             Assert.IsNotAssignableFrom(typeof(string), 5);
169 
170             // Constraint Syntax
171             Assert.That("Hello", Is.AssignableFrom(typeof(string)));
172             Assert.That(5, Is.Not.AssignableFrom(typeof(string)));
173 
174             // Inherited syntax
175             Expect("Hello", AssignableFrom(typeof(string)));
176             Expect(5, Not.AssignableFrom(typeof(string)));
177         }
178         #endregion
179 
180         #region StringConstraint Tests
181         [Test]
182         public void SubstringTests()
183         {
184             string phrase = "Hello World!";
185             string[] array = new string[] { "abc", "bad", "dba" };
186 
187             // Classic Syntax
188             StringAssert.Contains("World", phrase);
189 
190             // Constraint Syntax
191             Assert.That(phrase, Does.Contain("World"));
192             // Only available using new syntax
193             Assert.That(phrase, Does.Not.Contain("goodbye"));
194             Assert.That(phrase, Does.Contain("WORLD").IgnoreCase);
195             Assert.That(phrase, Does.Not.Contain("BYE").IgnoreCase);
196             Assert.That(array, Is.All.Contains("b"));
197 
198             // Inherited syntax
199             Expect(phrase, Contains("World"));
200             // Only available using new syntax
201             Expect(phrase, Not.Contains("goodbye"));
202             Expect(phrase, Contains("WORLD").IgnoreCase);
203             Expect(phrase, Not.Contains("BYE").IgnoreCase);
204             Expect(array, All.Contains("b"));
205         }
206 
207         [Test]
208         public void StartsWithTests()
209         {
210             string phrase = "Hello World!";
211             string[] greetings = new string[] { "Hello!", "Hi!", "Hola!" };
212 
213             // Classic syntax
214             StringAssert.StartsWith("Hello", phrase);
215 
216             // Constraint Syntax
217             Assert.That(phrase, Does.StartWith("Hello"));
218             // Only available using new syntax
219             Assert.That(phrase, Does.Not.StartWith("Hi!"));
220             Assert.That(phrase, Does.StartWith("HeLLo").IgnoreCase);
221             Assert.That(phrase, Does.Not.StartWith("HI").IgnoreCase);
222             Assert.That(greetings, Is.All.StartsWith("h").IgnoreCase);
223 
224             // Inherited syntax
225             Expect(phrase, StartsWith("Hello"));
226             // Only available using new syntax
227             Expect(phrase, Not.StartsWith("Hi!"));
228             Expect(phrase, StartsWith("HeLLo").IgnoreCase);
229             Expect(phrase, Not.StartsWith("HI").IgnoreCase);
230             Expect(greetings, All.StartsWith("h").IgnoreCase);
231         }
232 
233         [Test]
234         public void EndsWithTests()
235         {
236             string phrase = "Hello World!";
237             string[] greetings = new string[] { "Hello!", "Hi!", "Hola!" };
238 
239             // Classic Syntax
240             StringAssert.EndsWith("!", phrase);
241 
242             // Constraint Syntax
243             Assert.That(phrase, Does.EndWith("!"));
244             // Only available using new syntax
245             Assert.That(phrase, Does.Not.EndWith("?"));
246             Assert.That(phrase, Does.EndWith("WORLD!").IgnoreCase);
247             Assert.That(greetings, Is.All.EndsWith("!"));
248 
249             // Inherited syntax
250             Expect(phrase, EndsWith("!"));
251             // Only available using new syntax
252             Expect(phrase, Not.EndsWith("?"));
253             Expect(phrase, EndsWith("WORLD!").IgnoreCase);
254             Expect(greetings, All.EndsWith("!"));
255         }
256 
257         [Test]
258         public void EqualIgnoringCaseTests()
259         {
260             string phrase = "Hello World!";
261 
262             // Classic syntax
263             StringAssert.AreEqualIgnoringCase("hello world!", phrase);
264 
265             // Constraint Syntax
266             Assert.That(phrase, Is.EqualTo("hello world!").IgnoreCase);
267             //Only available using new syntax
268             Assert.That(phrase, Is.Not.EqualTo("goodbye world!").IgnoreCase);
269             Assert.That(new string[] { "Hello", "World" },
270                 Is.EqualTo(new object[] { "HELLO", "WORLD" }).IgnoreCase);
271             Assert.That(new string[] { "HELLO", "Hello", "hello" },
272                 Is.All.EqualTo("hello").IgnoreCase);
273 
274             // Inherited syntax
275             Expect(phrase, EqualTo("hello world!").IgnoreCase);
276             //Only available using new syntax
277             Expect(phrase, Not.EqualTo("goodbye world!").IgnoreCase);
278             Expect(new string[] { "Hello", "World" },
279                 EqualTo(new object[] { "HELLO", "WORLD" }).IgnoreCase);
280             Expect(new string[] { "HELLO", "Hello", "hello" },
281                 All.EqualTo("hello").IgnoreCase);
282         }
283 
284         [Test]
285         public void RegularExpressionTests()
286         {
287             string phrase = "Now is the time for all good men to come to the aid of their country.";
288             string[] quotes = new string[] { "Never say never", "It‘s never too late", "Nevermore!" };
289 
290             // Classic syntax
291             StringAssert.IsMatch("all good men", phrase);
292             StringAssert.IsMatch("Now.*come", phrase);
293 
294             // Constraint Syntax
295             Assert.That(phrase, Does.Match("all good men"));
296             Assert.That(phrase, Does.Match("Now.*come"));
297             // Only available using new syntax
298             Assert.That(phrase, Does.Not.Match("all.*men.*good"));
299             Assert.That(phrase, Does.Match("ALL").IgnoreCase);
300             Assert.That(quotes, Is.All.Matches("never").IgnoreCase);
301 
302             // Inherited syntax
303             Expect(phrase, Matches("all good men"));
304             Expect(phrase, Matches("Now.*come"));
305             // Only available using new syntax
306             Expect(phrase, Not.Matches("all.*men.*good"));
307             Expect(phrase, Matches("ALL").IgnoreCase);
308             Expect(quotes, All.Matches("never").IgnoreCase);
309         }
310         #endregion
311 
312         #region Equality Tests
313         [Test]
314         public void EqualityTests()
315         {
316             int[] i3 = new int[] { 1, 2, 3 };
317             double[] d3 = new double[] { 1.0, 2.0, 3.0 };
318             int[] iunequal = new int[] { 1, 3, 2 };
319 
320             // Classic Syntax
321             Assert.AreEqual(4, 2 + 2);
322             Assert.AreEqual(i3, d3);
323             Assert.AreNotEqual(5, 2 + 2);
324             Assert.AreNotEqual(i3, iunequal);
325 
326             // Constraint Syntax
327             Assert.That(2 + 2, Is.EqualTo(4));
328             Assert.That(2 + 2 == 4);
329             Assert.That(i3, Is.EqualTo(d3));
330             Assert.That(2 + 2, Is.Not.EqualTo(5));
331             Assert.That(i3, Is.Not.EqualTo(iunequal));
332 
333             // Inherited syntax
334             Expect(2 + 2, EqualTo(4));
335             Expect(2 + 2 == 4);
336             Expect(i3, EqualTo(d3));
337             Expect(2 + 2, Not.EqualTo(5));
338             Expect(i3, Not.EqualTo(iunequal));
339         }
340 
341         [Test]
342         public void EqualityTestsWithTolerance()
343         {
344             // CLassic syntax
345             Assert.AreEqual(5.0d, 4.99d, 0.05d);
346             Assert.AreEqual(5.0f, 4.99f, 0.05f);
347 
348             // Constraint Syntax
349             Assert.That(4.99d, Is.EqualTo(5.0d).Within(0.05d));
350             Assert.That(4.0d, Is.Not.EqualTo(5.0d).Within(0.5d));
351             Assert.That(4.99f, Is.EqualTo(5.0f).Within(0.05f));
352             Assert.That(4.99m, Is.EqualTo(5.0m).Within(0.05m));
353             Assert.That(3999999999u, Is.EqualTo(4000000000u).Within(5u));
354             Assert.That(499, Is.EqualTo(500).Within(5));
355             Assert.That(4999999999L, Is.EqualTo(5000000000L).Within(5L));
356             Assert.That(5999999999ul, Is.EqualTo(6000000000ul).Within(5ul));
357 
358             // Inherited syntax
359             Expect(4.99d, EqualTo(5.0d).Within(0.05d));
360             Expect(4.0d, Not.EqualTo(5.0d).Within(0.5d));
361             Expect(4.99f, EqualTo(5.0f).Within(0.05f));
362             Expect(4.99m, EqualTo(5.0m).Within(0.05m));
363             Expect(499u, EqualTo(500u).Within(5u));
364             Expect(499, EqualTo(500).Within(5));
365             Expect(4999999999L, EqualTo(5000000000L).Within(5L));
366             Expect(5999999999ul, EqualTo(6000000000ul).Within(5ul));
367         }
368 
369         [Test]
370         public void EqualityTestsWithTolerance_MixedFloatAndDouble()
371         {
372             // Bug Fix 1743844
373             Assert.That(2.20492d, Is.EqualTo(2.2d).Within(0.01f),
374                 "Double actual, Double expected, Single tolerance");
375             Assert.That(2.20492d, Is.EqualTo(2.2f).Within(0.01d),
376                 "Double actual, Single expected, Double tolerance");
377             Assert.That(2.20492d, Is.EqualTo(2.2f).Within(0.01f),
378                 "Double actual, Single expected, Single tolerance");
379             Assert.That(2.20492f, Is.EqualTo(2.2f).Within(0.01d),
380                 "Single actual, Single expected, Double tolerance");
381             Assert.That(2.20492f, Is.EqualTo(2.2d).Within(0.01d),
382                 "Single actual, Double expected, Double tolerance");
383             Assert.That(2.20492f, Is.EqualTo(2.2d).Within(0.01f),
384                 "Single actual, Double expected, Single tolerance");
385         }
386 
387         [Test]
388         public void EqualityTestsWithTolerance_MixingTypesGenerally()
389         {
390             // Extending tolerance to all numeric types
391             Assert.That(202d, Is.EqualTo(200d).Within(2),
392                 "Double actual, Double expected, int tolerance");
393             Assert.That(4.87m, Is.EqualTo(5).Within(.25),
394                 "Decimal actual, int expected, Double tolerance");
395             Assert.That(4.87m, Is.EqualTo(5ul).Within(1),
396                 "Decimal actual, ulong expected, int tolerance");
397             Assert.That(487, Is.EqualTo(500).Within(25),
398                 "int actual, int expected, int tolerance");
399             Assert.That(487u, Is.EqualTo(500).Within(25),
400                 "uint actual, int expected, int tolerance");
401             Assert.That(487L, Is.EqualTo(500).Within(25),
402                 "long actual, int expected, int tolerance");
403             Assert.That(487ul, Is.EqualTo(500).Within(25),
404                 "ulong actual, int expected, int tolerance");
405         }
406         #endregion
407 
408         #region Comparison Tests
409         [Test]
410         public void ComparisonTests()
411         {
412             // Classic Syntax
413             Assert.Greater(7, 3);
414             Assert.GreaterOrEqual(7, 3);
415             Assert.GreaterOrEqual(7, 7);
416 
417             // Constraint Syntax
418             Assert.That(7, Is.GreaterThan(3));
419             Assert.That(7, Is.GreaterThanOrEqualTo(3));
420             Assert.That(7, Is.AtLeast(3));
421             Assert.That(7, Is.GreaterThanOrEqualTo(7));
422             Assert.That(7, Is.AtLeast(7));
423 
424             // Inherited syntax
425             Expect(7, GreaterThan(3));
426             Expect(7, GreaterThanOrEqualTo(3));
427             Expect(7, AtLeast(3));
428             Expect(7, GreaterThanOrEqualTo(7));
429             Expect(7, AtLeast(7));
430 
431             // Classic syntax
432             Assert.Less(3, 7);
433             Assert.LessOrEqual(3, 7);
434             Assert.LessOrEqual(3, 3);
435 
436             // Constraint Syntax
437             Assert.That(3, Is.LessThan(7));
438             Assert.That(3, Is.LessThanOrEqualTo(7));
439             Assert.That(3, Is.AtMost(7));
440             Assert.That(3, Is.LessThanOrEqualTo(3));
441             Assert.That(3, Is.AtMost(3));
442 
443             // Inherited syntax
444             Expect(3, LessThan(7));
445             Expect(3, LessThanOrEqualTo(7));
446             Expect(3, AtMost(7));
447             Expect(3, LessThanOrEqualTo(3));
448             Expect(3, AtMost(3));
449         }
450         #endregion
451 
452         #region Collection Tests
453         [Test]
454         public void AllItemsTests()
455         {
456             object[] ints = new object[] { 1, 2, 3, 4 };
457             object[] doubles = new object[] { 0.99, 2.1, 3.0, 4.05 };
458             object[] strings = new object[] { "abc", "bad", "cab", "bad", "dad" };
459 
460             // Classic syntax
461             CollectionAssert.AllItemsAreNotNull(ints);
462             CollectionAssert.AllItemsAreInstancesOfType(ints, typeof(int));
463             CollectionAssert.AllItemsAreInstancesOfType(strings, typeof(string));
464             CollectionAssert.AllItemsAreUnique(ints);
465 
466             // Constraint Syntax
467             Assert.That(ints, Is.All.Not.Null);
468             Assert.That(ints, Has.None.Null);
469             Assert.That(ints, Is.All.InstanceOf(typeof(int)));
470             Assert.That(ints, Has.All.InstanceOf(typeof(int)));
471             Assert.That(strings, Is.All.InstanceOf(typeof(string)));
472             Assert.That(strings, Has.All.InstanceOf(typeof(string)));
473             Assert.That(ints, Is.Unique);
474             // Only available using new syntax
475             Assert.That(strings, Is.Not.Unique);
476             Assert.That(ints, Is.All.GreaterThan(0));
477             Assert.That(ints, Has.All.GreaterThan(0));
478             Assert.That(ints, Has.None.LessThanOrEqualTo(0));
479             Assert.That(strings, Is.All.Contains("a"));
480             Assert.That(strings, Has.All.Contains("a"));
481             Assert.That(strings, Has.Some.StartsWith("ba"));
482             Assert.That(strings, Has.Some.Property("Length").EqualTo(3));
483             Assert.That(strings, Has.Some.StartsWith("BA").IgnoreCase);
484             Assert.That(doubles, Has.Some.EqualTo(1.0).Within(.05));
485 
486             // Inherited syntax
487             Expect(ints, All.Not.Null);
488             Expect(ints, None.Null);
489             Expect(ints, All.InstanceOf(typeof(int)));
490             Expect(strings, All.InstanceOf(typeof(string)));
491             Expect(ints, Unique);
492             // Only available using new syntax
493             Expect(strings, Not.Unique);
494             Expect(ints, All.GreaterThan(0));
495             Expect(ints, None.LessThanOrEqualTo(0));
496             Expect(strings, All.Contains("a"));
497             Expect(strings, Some.StartsWith("ba"));
498             Expect(strings, Some.StartsWith("BA").IgnoreCase);
499             Expect(doubles, Some.EqualTo(1.0).Within(.05));
500         }
501 
502         [Test]
503         public void SomeItemTests()
504         {
505             object[] mixed = new object[] { 1, 2, "3", null, "four", 100 };
506             object[] strings = new object[] { "abc", "bad", "cab", "bad", "dad" };
507 
508             // Not available using the classic syntax
509 
510             // Constraint Syntax
511             Assert.That(mixed, Has.Some.Null);
512             Assert.That(mixed, Has.Some.InstanceOf(typeof(int)));
513             Assert.That(mixed, Has.Some.InstanceOf(typeof(string)));
514             Assert.That(strings, Has.Some.StartsWith("ba"));
515             Assert.That(strings, Has.Some.Not.StartsWith("ba"));
516 
517             // Inherited syntax
518             Expect(mixed, Some.Null);
519             Expect(mixed, Some.InstanceOf(typeof(int)));
520             Expect(mixed, Some.InstanceOf(typeof(string)));
521             Expect(strings, Some.StartsWith("ba"));
522             Expect(strings, Some.Not.StartsWith("ba"));
523         }
524 
525         [Test]
526         public void NoItemTests()
527         {
528             object[] ints = new object[] { 1, 2, 3, 4, 5 };
529             object[] strings = new object[] { "abc", "bad", "cab", "bad", "dad" };
530 
531             // Not available using the classic syntax
532 
533             // Constraint Syntax
534             Assert.That(ints, Has.None.Null);
535             Assert.That(ints, Has.None.InstanceOf(typeof(string)));
536             Assert.That(ints, Has.None.GreaterThan(99));
537             Assert.That(strings, Has.None.StartsWith("qu"));
538 
539             // Inherited syntax
540             Expect(ints, None.Null);
541             Expect(ints, None.InstanceOf(typeof(string)));
542             Expect(ints, None.GreaterThan(99));
543             Expect(strings, None.StartsWith("qu"));
544         }
545 
546         [Test]
547         public void CollectionContainsTests()
548         {
549             int[] iarray = new int[] { 1, 2, 3 };
550             string[] sarray = new string[] { "a", "b", "c" };
551 
552             // Classic syntax
553             Assert.Contains(3, iarray);
554             Assert.Contains("b", sarray);
555             CollectionAssert.Contains(iarray, 3);
556             CollectionAssert.Contains(sarray, "b");
557             CollectionAssert.DoesNotContain(sarray, "x");
558             // Showing that Contains uses NUnit equality
559             CollectionAssert.Contains(iarray, 1.0d);
560 
561             // Constraint Syntax
562             Assert.That(iarray, Has.Member(3));
563             Assert.That(sarray, Has.Member("b"));
564             Assert.That(sarray, Has.No.Member("x"));
565             // Showing that Contains uses NUnit equality
566             Assert.That(iarray, Has.Member(1.0d));
567 
568             // Only available using the new syntax
569             // Note that EqualTo and SameAs do NOT give
570             // identical results to Contains because 
571             // Contains uses Object.Equals()
572             Assert.That(iarray, Has.Some.EqualTo(3));
573             Assert.That(iarray, Has.Member(3));
574             Assert.That(sarray, Has.Some.EqualTo("b"));
575             Assert.That(sarray, Has.None.EqualTo("x"));
576             Assert.That(iarray, Has.None.SameAs(1.0d));
577             Assert.That(iarray, Has.All.LessThan(10));
578             Assert.That(sarray, Has.All.Length.EqualTo(1));
579             Assert.That(sarray, Has.None.Property("Length").GreaterThan(3));
580 
581             // Inherited syntax
582             Expect(iarray, Contains(3));
583             Expect(sarray, Contains("b"));
584             Expect(sarray, Not.Contains("x"));
585 
586             // Only available using new syntax
587             // Note that EqualTo and SameAs do NOT give
588             // identical results to Contains because 
589             // Contains uses Object.Equals()
590             Expect(iarray, Some.EqualTo(3));
591             Expect(sarray, Some.EqualTo("b"));
592             Expect(sarray, None.EqualTo("x"));
593             Expect(iarray, All.LessThan(10));
594             Expect(sarray, All.Length.EqualTo(1));
595             Expect(sarray, None.Property("Length").GreaterThan(3));
596         }
597 
598         [Test]
599         public void CollectionEquivalenceTests()
600         {
601             int[] ints1to5 = new int[] { 1, 2, 3, 4, 5 };
602             int[] twothrees = new int[] { 1, 2, 3, 3, 4, 5 };
603             int[] twofours = new int[] { 1, 2, 3, 4, 4, 5 };
604 
605             // Classic syntax
606             CollectionAssert.AreEquivalent(new int[] { 2, 1, 4, 3, 5 }, ints1to5);
607             CollectionAssert.AreNotEquivalent(new int[] { 2, 2, 4, 3, 5 }, ints1to5);
608             CollectionAssert.AreNotEquivalent(new int[] { 2, 4, 3, 5 }, ints1to5);
609             CollectionAssert.AreNotEquivalent(new int[] { 2, 2, 1, 1, 4, 3, 5 }, ints1to5);
610             CollectionAssert.AreNotEquivalent(twothrees, twofours);
611 
612             // Constraint Syntax
613             Assert.That(new int[] { 2, 1, 4, 3, 5 }, Is.EquivalentTo(ints1to5));
614             Assert.That(new int[] { 2, 2, 4, 3, 5 }, Is.Not.EquivalentTo(ints1to5));
615             Assert.That(new int[] { 2, 4, 3, 5 }, Is.Not.EquivalentTo(ints1to5));
616             Assert.That(new int[] { 2, 2, 1, 1, 4, 3, 5 }, Is.Not.EquivalentTo(ints1to5));
617 
618             // Inherited syntax
619             Expect(new int[] { 2, 1, 4, 3, 5 }, EquivalentTo(ints1to5));
620             Expect(new int[] { 2, 2, 4, 3, 5 }, Not.EquivalentTo(ints1to5));
621             Expect(new int[] { 2, 4, 3, 5 }, Not.EquivalentTo(ints1to5));
622             Expect(new int[] { 2, 2, 1, 1, 4, 3, 5 }, Not.EquivalentTo(ints1to5));
623         }
624 
625         [Test]
626         public void SubsetTests()
627         {
628             int[] ints1to5 = new int[] { 1, 2, 3, 4, 5 };
629 
630             // Classic syntax
631             CollectionAssert.IsSubsetOf(new int[] { 1, 3, 5 }, ints1to5);
632             CollectionAssert.IsSubsetOf(new int[] { 1, 2, 3, 4, 5 }, ints1to5);
633             CollectionAssert.IsNotSubsetOf(new int[] { 2, 4, 6 }, ints1to5);
634             CollectionAssert.IsNotSubsetOf(new int[] { 1, 2, 2, 2, 5 }, ints1to5);
635 
636             // Constraint Syntax
637             Assert.That(new int[] { 1, 3, 5 }, Is.SubsetOf(ints1to5));
638             Assert.That(new int[] { 1, 2, 3, 4, 5 }, Is.SubsetOf(ints1to5));
639             Assert.That(new int[] { 2, 4, 6 }, Is.Not.SubsetOf(ints1to5));
640 
641             // Inherited syntax
642             Expect(new int[] { 1, 3, 5 }, SubsetOf(ints1to5));
643             Expect(new int[] { 1, 2, 3, 4, 5 }, SubsetOf(ints1to5));
644             Expect(new int[] { 2, 4, 6 }, Not.SubsetOf(ints1to5));
645         }
646         #endregion
647 
648         #region Property Tests
649         [Test]
650         public void PropertyTests()
651         {
652             string[] array = { "abc", "bca", "xyz", "qrs" };
653             string[] array2 = { "a", "ab", "abc" };
654             ArrayList list = new ArrayList(array);
655 
656             // Not available using the classic syntax
657 
658             // Constraint Syntax
659             Assert.That(list, Has.Property("Count"));
660             Assert.That(list, Has.No.Property("Length"));
661 
662             Assert.That("Hello", Has.Length.EqualTo(5));
663             Assert.That("Hello", Has.Length.LessThan(10));
664             Assert.That("Hello", Has.Property("Length").EqualTo(5));
665             Assert.That("Hello", Has.Property("Length").GreaterThan(3));
666 
667             Assert.That(array, Has.Property("Length").EqualTo(4));
668             Assert.That(array, Has.Length.EqualTo(4));
669             Assert.That(array, Has.Property("Length").LessThan(10));
670 
671             Assert.That(array, Has.All.Property("Length").EqualTo(3));
672             Assert.That(array, Has.All.Length.EqualTo(3));
673             Assert.That(array, Is.All.Length.EqualTo(3));
674             Assert.That(array, Has.All.Property("Length").EqualTo(3));
675             Assert.That(array, Is.All.Property("Length").EqualTo(3));
676 
677             Assert.That(array2, Has.Some.Property("Length").EqualTo(2));
678             Assert.That(array2, Has.Some.Length.EqualTo(2));
679             Assert.That(array2, Has.Some.Property("Length").GreaterThan(2));
680 
681             Assert.That(array2, Is.Not.Property("Length").EqualTo(4));
682             Assert.That(array2, Is.Not.Length.EqualTo(4));
683             Assert.That(array2, Has.No.Property("Length").GreaterThan(3));
684 
685             Assert.That(List.Map(array2).Property("Length"), Is.EqualTo(new int[] { 1, 2, 3 }));
686             Assert.That(List.Map(array2).Property("Length"), Is.EquivalentTo(new int[] { 3, 2, 1 }));
687             Assert.That(List.Map(array2).Property("Length"), Is.SubsetOf(new int[] { 1, 2, 3, 4, 5 }));
688             Assert.That(List.Map(array2).Property("Length"), Is.Unique);
689 
690             Assert.That(list, Has.Count.EqualTo(4));
691 
692             // Inherited syntax
693             Expect(list, Property("Count"));
694             Expect(list, Not.Property("Nada"));
695 
696             Expect("Hello", Length.EqualTo(5));
697             Expect("Hello", Property("Length").EqualTo(5));
698             Expect("Hello", Property("Length").GreaterThan(0));
699 
700             Expect(array, Property("Length").EqualTo(4));
701             Expect(array, Length.EqualTo(4));
702             Expect(array, Property("Length").LessThan(10));
703 
704             Expect(array, All.Length.EqualTo(3));
705             Expect(array, All.Property("Length").EqualTo(3));
706 
707             Expect(array2, Some.Property("Length").EqualTo(2));
708             Expect(array2, Some.Length.EqualTo(2));
709             Expect(array2, Some.Property("Length").GreaterThan(2));
710 
711             Expect(array2, None.Property("Length").EqualTo(4));
712             Expect(array2, None.Length.EqualTo(4));
713             Expect(array2, None.Property("Length").GreaterThan(3));
714 
715             Expect(Map(array2).Property("Length"), EqualTo(new int[] { 1, 2, 3 }));
716             Expect(Map(array2).Property("Length"), EquivalentTo(new int[] { 3, 2, 1 }));
717             Expect(Map(array2).Property("Length"), SubsetOf(new int[] { 1, 2, 3, 4, 5 }));
718             Expect(Map(array2).Property("Length"), Unique);
719 
720             Expect(list, Count.EqualTo(4));
721 
722         }
723         #endregion
724 
725         #region Not Tests
726         [Test]
727         public void NotTests()
728         {
729             // Not available using the classic syntax
730 
731             // Constraint Syntax
732             Assert.That(42, Is.Not.Null);
733             Assert.That(42, Is.Not.True);
734             Assert.That(42, Is.Not.False);
735             Assert.That(2.5, Is.Not.NaN);
736             Assert.That(2 + 2, Is.Not.EqualTo(3));
737             Assert.That(2 + 2, Is.Not.Not.EqualTo(4));
738             Assert.That(2 + 2, Is.Not.Not.Not.EqualTo(5));
739 
740             // Inherited syntax
741             Expect(42, Not.Null);
742             Expect(42, Not.True);
743             Expect(42, Not.False);
744             Expect(2.5, Not.NaN);
745             Expect(2 + 2, Not.EqualTo(3));
746             Expect(2 + 2, Not.Not.EqualTo(4));
747             Expect(2 + 2, Not.Not.Not.EqualTo(5));
748         }
749         #endregion
750 
751         #region Operator Tests
752         [Test]
753         public void NotOperator()
754         {
755             // The ! operator is only available in the new syntax
756             Assert.That(42, !Is.Null);
757             // Inherited syntax
758             Expect(42, !Null);
759         }
760 
761         [Test]
762         public void AndOperator()
763         {
764             // The & operator is only available in the new syntax
765             Assert.That(7, Is.GreaterThan(5) & Is.LessThan(10));
766             // Inherited syntax
767             Expect(7, GreaterThan(5) & LessThan(10));
768         }
769 
770         [Test]
771         public void OrOperator()
772         {
773             // The | operator is only available in the new syntax
774             Assert.That(3, Is.LessThan(5) | Is.GreaterThan(10));
775             Expect(3, LessThan(5) | GreaterThan(10));
776         }
777 
778         [Test]
779         public void ComplexTests()
780         {
781             Assert.That(7, Is.Not.Null & Is.Not.LessThan(5) & Is.Not.GreaterThan(10));
782             Expect(7, Not.Null & Not.LessThan(5) & Not.GreaterThan(10));
783 
784             Assert.That(7, !Is.Null & !Is.LessThan(5) & !Is.GreaterThan(10));
785             Expect(7, !Null & !LessThan(5) & !GreaterThan(10));
786 
787             // No longer works at all under 3.0
788             // TODO: Evaluate why we wanted to use null in this setting in the first place
789 #if false
790                 // TODO: Remove #if when mono compiler can handle null
791 #if MONO
792                 Constraint x = null;
793                 Assert.That(7, !x & !Is.LessThan(5) & !Is.GreaterThan(10));
794                 Expect(7, !x & !LessThan(5) & !GreaterThan(10));
795 #else
796                 Assert.That(7, !(Constraint)null & !Is.LessThan(5) & !Is.GreaterThan(10));
797                 Expect(7, !(Constraint)null & !LessThan(5) & !GreaterThan(10));
798 #endif
799 #endif
800         }
801         #endregion
802 
803         #region Invalid Code Tests
804         // This method contains assertions that should not compile
805         // You can check by uncommenting it.
806         //public void WillNotCompile()
807         //{
808         //    Assert.That(42, Is.Not);
809         //    Assert.That(42, Is.All);
810         //    Assert.That(42, Is.Null.Not);
811         //    Assert.That(42, Is.Not.Null.GreaterThan(10));
812         //    Assert.That(42, Is.GreaterThan(10).LessThan(99));
813 
814         //    object[] c = new object[0];
815         //    Assert.That(c, Is.Null.All);
816         //    Assert.That(c, Is.Not.All);
817         //    Assert.That(c, Is.All.Not);
818         //}
819         #endregion
820     }
821 
822 #endregion
Nunit 单元测试

 

单元测试参考资料

  • MSDN - Microsoft.VisualStudio.TestTools.UnitTesting
  • 单元测试之道
  • VS2012 Unit Test 个人学习汇总(含目录)
  • 单元测试的优点
  • 对比MS Test与NUnit Test框架

走进 .Net 单元测试