美文网首页.NET Amazing .NETC#
走进 .Net 单元测试

走进 .Net 单元测试

作者: 天天向上卡索 | 来源:发表于2016-10-18 17:16 被阅读468次

    走进 .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 特性标记的方法。

    单元测试 使用示例

    using Microsoft.VisualStudio.TestTools.UnitTesting;
    
    namespace ConsoleApplication1Test
    {
        [TestClass]
        public class MainTest
        {
            #region TestFail
    
            [TestMethod]
            public void TestFail0()
            {
                Assert.Fail();
            }
    
            [TestMethod]
            public void TestFail1()
            {
                Assert.Fail("Test is fail");
            }
    
            [TestMethod]
            public void TestFail2()
            {
                Assert.Fail("Test3 is fail,{0}", "hahaha");
            }
            #endregion
    
            #region TestInconclusive 忽略
            [TestMethod]
            public void TestInconclusive0()
            {
                Assert.Inconclusive();
            }
    
            [TestMethod]
            public void TestInconclusive1()
            {
                Assert.Inconclusive("Inconclusive");
            }
    
            [TestMethod]
            public void TestInconclusive2()
            {
                Assert.Inconclusive("Inconclusive,{0}", "hehehe");
            }
            #endregion
    
            #region LogicTest
    
            #region Null
            [TestMethod]
            public void IsNullTest()
            {
                Assert.IsNull(null);
            }
    
            [TestMethod]
            public void IsNotNullTest()
            {
                Assert.IsNotNull(1);
            } 
            #endregion
    
            #region True || False
            [TestMethod]
            public void IsTrueTest()
            {
                Assert.IsTrue(1 == 1);
            }
    
            [TestMethod]
            public void IsFalseTest()
            {
                Assert.IsFalse(1 > 2);
            } 
            #endregion
    
            #region AreSame
            [TestMethod]
            public void AreSameTest()
            {
                //不要向 AreSame() 传递值类型的值,因为他们转换为 Object 后永久不会相等,值类型的值比较请使用 AreEqual()
                Assert.AreSame(1, 1);
            }
    
            [TestMethod]
            public void AreSameTest1()
            {
                object obj = new object(), obj1 = obj;
                Assert.AreSame(obj, obj1, "same");
            }
    
            [TestMethod]
            public void StringAreSameTest0()
            {
                string str1 = "hello", str2 = "hello";
                Assert.AreSame(str1, str2);
            }
    
            [TestMethod]
            public void StringAreSameTest1()
            {
                string str1 = "hello", str2 = "Hello";
                Assert.AreSame(str1, str2);
            }
    
            [TestMethod]
            public void AreNotSameTest()
            {
                object obj = new object(), obj1 = new object();
                Assert.AreNotSame(obj, obj1);
            } 
            #endregion
    
            #region AreEqual
            [TestMethod]
            public void AreEqualTest()
            {
                Assert.AreEqual(1, 1);
            }
    
            [TestMethod]
            public void AreNotEqualTest()
            {
                Assert.AreNotEqual(1, 2);
            }
    
            [TestMethod]
            public void AreEqualTest1()
            {
                object obj = new object(), obj1 = obj;
                Assert.AreEqual(obj, obj1);
            }
    
            [TestMethod]
            public void AreNotEqualTest1()
            {
                object obj = new object(), obj1 = new object();
                Assert.AreNotEqual(obj, obj1);
            }
    
            [TestMethod]
            public void AreEqualTest2()
            {
                object obj = new object(), obj1 = new object();
                Assert.AreEqual(obj, obj1);
                // Assert.Equals()不用于断言,请使用 Assert.AreEquals() 或 Assert.AreNotEquals()
                //Assert.Equals(obj, obj1);
            }
    
            [TestMethod]
            public void StringAreEqualTest0()
            {
                string str = "hello", str1 = "hello";
                Assert.AreEqual(str, str1);
            }
    
            [TestMethod]
            public void StringAreEqualTest1()
            {
                string str = "hello", str1 = "Hello";
                Assert.AreEqual(str, str1, true);
            } 
            #endregion
    
            #region IsInstanceOfType
    
            [TestMethod]
            public void IsInstanceOfTypeTest()
            {
                B b = new B();
                Assert.IsInstanceOfType(b, typeof(A));
            }
    
            [TestMethod]
            public void IsNotInstanceOfTypeTest()
            {
                A a = new A();
                Assert.IsNotInstanceOfType(a, typeof(B));
            }
            #endregion
    
            #endregion
    
            #region 测试初始化和清理
            [AssemblyInitialize()]
            public static void AssemblyInit(TestContext context)
            {
                System.Console.WriteLine("AssemblyInit " + context.TestName);
            }
    
            [ClassInitialize()]
            public static void ClassInit(TestContext context)
            {
                System.Console.WriteLine("ClassInit " + context.TestName);
            }
    
            [TestInitialize]
            public void Initialize()
            {
                System.Console.WriteLine("TestMethodInit");
            }
    
            [TestCleanup]
            public void Cleanup()
            {
                System.Console.WriteLine("TestMethodCleanup");
            }
    
            [ClassCleanup]
            public static void ClassCleanup()
            {
                System.Console.WriteLine("ClassCleanup");
            }
    
            [AssemblyCleanup]
            public static void AssemblyCleanup()
            {
                System.Console.WriteLine("AssemblyCleanup");
            } 
            #endregion
        }
    
        public class A { }
    
        public class B : A { }
    
    }
    

    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

    同时支持两种测试框架

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

    #if !NUNIT 
    using Microsoft.VisualStudio.TestTools.UnitTesting; 
    using Category = Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute; 
    #else 
    using NUnit.Framework; 
    using TestClass = NUnit.Framework.TestFixtureAttribute; 
    using TestMethod = NUnit.Framework.TestAttribute; 
    using TestInitialize = NUnit.Framework.SetUpAttribute; 
    using TestCleanup = NUnit.Framework.TearDownAttribute; 
    using TestContext = System.Object; 
    using ClassCleanup = NUnit.Framework.TestFixtureTearDownAttribute; 
    using ClassInitialize = NUnit.Framework.TestFixtureSetUpAttribute; 
    #endif
    

    Nunit测试使用示例

    #region NUNIT
    
        /// <summary>
        /// This test fixture attempts to exercise all the syntactic
        /// variations of Assert without getting into failures, errors 
        /// or corner cases.Thus, some of the tests may be duplicated 
        /// in other fixtures.
        /// 
        /// Each test performs the same operations using the classic
        /// syntax(if available) and the new syntax in both the
        /// helper-based and inherited forms.
        /// 
        /// This Fixture will eventually be duplicated in other
        /// supported languages. 
        /// </summary>
        [TestFixture]
        public class AssertSyntaxTests : AssertionHelper
        {
            #region Simple Constraint Tests
            [Test]
            public void IsNull()
            {
                object nada = null;
    
                // Classic syntax
                Assert.IsNull(nada);
    
                // Constraint Syntax
                Assert.That(nada, Is.Null);
    
                // Inherited syntax
                Expect(nada, Null);
            }
    
            [Test]
            public void IsNotNull()
            {
                // Classic syntax
                Assert.IsNotNull(42);
    
                // Constraint Syntax
                Assert.That(42, Is.Not.Null);
    
                // Inherited syntax
                Expect(42, Not.Null);
            }
    
            [Test]
            public void IsTrue()
            {
                // Classic syntax
                Assert.IsTrue(2 + 2 == 4);
    
                // Constraint Syntax
                Assert.That(2 + 2 == 4, Is.True);
                Assert.That(2 + 2 == 4);
    
                // Inherited syntax
                Expect(2 + 2 == 4, True);
                Expect(2 + 2 == 4);
            }
    
            [Test]
            public void IsFalse()
            {
                // Classic syntax
                Assert.IsFalse(2 + 2 == 5);
    
                // Constraint Syntax
                Assert.That(2 + 2 == 5, Is.False);
    
                // Inherited syntax
                Expect(2 + 2 == 5, False);
            }
    
            [Test]
            public void IsNaN()
            {
                double d = double.NaN;
                float f = float.NaN;
    
                // Classic syntax
                Assert.IsNaN(d);
                Assert.IsNaN(f);
    
                // Constraint Syntax
                Assert.That(d, Is.NaN);
                Assert.That(f, Is.NaN);
    
                // Inherited syntax
                Expect(d, NaN);
                Expect(f, NaN);
            }
    
            [Test]
            public void EmptyStringTests()
            {
                // Classic syntax
                Assert.IsEmpty("");
                Assert.IsNotEmpty("Hello!");
    
                // Constraint Syntax
                Assert.That("", Is.Empty);
                Assert.That("Hello!", Is.Not.Empty);
    
                // Inherited syntax
                Expect("", Empty);
                Expect("Hello!", Not.Empty);
            }
    
            [Test]
            public void EmptyCollectionTests()
            {
                // Classic syntax
                Assert.IsEmpty(new bool[0]);
                Assert.IsNotEmpty(new int[] { 1, 2, 3 });
    
                // Constraint Syntax
                Assert.That(new bool[0], Is.Empty);
                Assert.That(new int[] { 1, 2, 3 }, Is.Not.Empty);
    
                // Inherited syntax
                Expect(new bool[0], Empty);
                Expect(new int[] { 1, 2, 3 }, Not.Empty);
            }
            #endregion
    
            #region TypeConstraint Tests
            [Test]
            public void ExactTypeTests()
            {
                // Classic syntax workarounds
                Assert.AreEqual(typeof(string), "Hello".GetType());
                Assert.AreEqual("System.String", "Hello".GetType().FullName);
                Assert.AreNotEqual(typeof(int), "Hello".GetType());
                Assert.AreNotEqual("System.Int32", "Hello".GetType().FullName);
    
                // Constraint Syntax
                Assert.That("Hello", Is.TypeOf(typeof(string)));
                Assert.That("Hello", Is.Not.TypeOf(typeof(int)));
    
                // Inherited syntax
                Expect("Hello", TypeOf(typeof(string)));
                Expect("Hello", Not.TypeOf(typeof(int)));
            }
    
            [Test]
            public void InstanceOfTests()
            {
                // Classic syntax
                Assert.IsInstanceOf(typeof(string), "Hello");
                Assert.IsNotInstanceOf(typeof(string), 5);
    
                // Constraint Syntax
                Assert.That("Hello", Is.InstanceOf(typeof(string)));
                Assert.That(5, Is.Not.InstanceOf(typeof(string)));
    
                // Inherited syntax
                Expect("Hello", InstanceOf(typeof(string)));
                Expect(5, Not.InstanceOf(typeof(string)));
            }
    
            [Test]
            public void AssignableFromTypeTests()
            {
                // Classic syntax
                Assert.IsAssignableFrom(typeof(string), "Hello");
                Assert.IsNotAssignableFrom(typeof(string), 5);
    
                // Constraint Syntax
                Assert.That("Hello", Is.AssignableFrom(typeof(string)));
                Assert.That(5, Is.Not.AssignableFrom(typeof(string)));
    
                // Inherited syntax
                Expect("Hello", AssignableFrom(typeof(string)));
                Expect(5, Not.AssignableFrom(typeof(string)));
            }
            #endregion
    
            #region StringConstraint Tests
            [Test]
            public void SubstringTests()
            {
                string phrase = "Hello World!";
                string[] array = new string[] { "abc", "bad", "dba" };
    
                // Classic Syntax
                StringAssert.Contains("World", phrase);
    
                // Constraint Syntax
                Assert.That(phrase, Does.Contain("World"));
                // Only available using new syntax
                Assert.That(phrase, Does.Not.Contain("goodbye"));
                Assert.That(phrase, Does.Contain("WORLD").IgnoreCase);
                Assert.That(phrase, Does.Not.Contain("BYE").IgnoreCase);
                Assert.That(array, Is.All.Contains("b"));
    
                // Inherited syntax
                Expect(phrase, Contains("World"));
                // Only available using new syntax
                Expect(phrase, Not.Contains("goodbye"));
                Expect(phrase, Contains("WORLD").IgnoreCase);
                Expect(phrase, Not.Contains("BYE").IgnoreCase);
                Expect(array, All.Contains("b"));
            }
    
            [Test]
            public void StartsWithTests()
            {
                string phrase = "Hello World!";
                string[] greetings = new string[] { "Hello!", "Hi!", "Hola!" };
    
                // Classic syntax
                StringAssert.StartsWith("Hello", phrase);
    
                // Constraint Syntax
                Assert.That(phrase, Does.StartWith("Hello"));
                // Only available using new syntax
                Assert.That(phrase, Does.Not.StartWith("Hi!"));
                Assert.That(phrase, Does.StartWith("HeLLo").IgnoreCase);
                Assert.That(phrase, Does.Not.StartWith("HI").IgnoreCase);
                Assert.That(greetings, Is.All.StartsWith("h").IgnoreCase);
    
                // Inherited syntax
                Expect(phrase, StartsWith("Hello"));
                // Only available using new syntax
                Expect(phrase, Not.StartsWith("Hi!"));
                Expect(phrase, StartsWith("HeLLo").IgnoreCase);
                Expect(phrase, Not.StartsWith("HI").IgnoreCase);
                Expect(greetings, All.StartsWith("h").IgnoreCase);
            }
    
            [Test]
            public void EndsWithTests()
            {
                string phrase = "Hello World!";
                string[] greetings = new string[] { "Hello!", "Hi!", "Hola!" };
    
                // Classic Syntax
                StringAssert.EndsWith("!", phrase);
    
                // Constraint Syntax
                Assert.That(phrase, Does.EndWith("!"));
                // Only available using new syntax
                Assert.That(phrase, Does.Not.EndWith("?"));
                Assert.That(phrase, Does.EndWith("WORLD!").IgnoreCase);
                Assert.That(greetings, Is.All.EndsWith("!"));
    
                // Inherited syntax
                Expect(phrase, EndsWith("!"));
                // Only available using new syntax
                Expect(phrase, Not.EndsWith("?"));
                Expect(phrase, EndsWith("WORLD!").IgnoreCase);
                Expect(greetings, All.EndsWith("!"));
            }
    
            [Test]
            public void EqualIgnoringCaseTests()
            {
                string phrase = "Hello World!";
    
                // Classic syntax
                StringAssert.AreEqualIgnoringCase("hello world!", phrase);
    
                // Constraint Syntax
                Assert.That(phrase, Is.EqualTo("hello world!").IgnoreCase);
                //Only available using new syntax
                Assert.That(phrase, Is.Not.EqualTo("goodbye world!").IgnoreCase);
                Assert.That(new string[] { "Hello", "World" },
                    Is.EqualTo(new object[] { "HELLO", "WORLD" }).IgnoreCase);
                Assert.That(new string[] { "HELLO", "Hello", "hello" },
                    Is.All.EqualTo("hello").IgnoreCase);
    
                // Inherited syntax
                Expect(phrase, EqualTo("hello world!").IgnoreCase);
                //Only available using new syntax
                Expect(phrase, Not.EqualTo("goodbye world!").IgnoreCase);
                Expect(new string[] { "Hello", "World" },
                    EqualTo(new object[] { "HELLO", "WORLD" }).IgnoreCase);
                Expect(new string[] { "HELLO", "Hello", "hello" },
                    All.EqualTo("hello").IgnoreCase);
            }
    
            [Test]
            public void RegularExpressionTests()
            {
                string phrase = "Now is the time for all good men to come to the aid of their country.";
                string[] quotes = new string[] { "Never say never", "It's never too late", "Nevermore!" };
    
                // Classic syntax
                StringAssert.IsMatch("all good men", phrase);
                StringAssert.IsMatch("Now.*come", phrase);
    
                // Constraint Syntax
                Assert.That(phrase, Does.Match("all good men"));
                Assert.That(phrase, Does.Match("Now.*come"));
                // Only available using new syntax
                Assert.That(phrase, Does.Not.Match("all.*men.*good"));
                Assert.That(phrase, Does.Match("ALL").IgnoreCase);
                Assert.That(quotes, Is.All.Matches("never").IgnoreCase);
    
                // Inherited syntax
                Expect(phrase, Matches("all good men"));
                Expect(phrase, Matches("Now.*come"));
                // Only available using new syntax
                Expect(phrase, Not.Matches("all.*men.*good"));
                Expect(phrase, Matches("ALL").IgnoreCase);
                Expect(quotes, All.Matches("never").IgnoreCase);
            }
            #endregion
    
            #region Equality Tests
            [Test]
            public void EqualityTests()
            {
                int[] i3 = new int[] { 1, 2, 3 };
                double[] d3 = new double[] { 1.0, 2.0, 3.0 };
                int[] iunequal = new int[] { 1, 3, 2 };
    
                // Classic Syntax
                Assert.AreEqual(4, 2 + 2);
                Assert.AreEqual(i3, d3);
                Assert.AreNotEqual(5, 2 + 2);
                Assert.AreNotEqual(i3, iunequal);
    
                // Constraint Syntax
                Assert.That(2 + 2, Is.EqualTo(4));
                Assert.That(2 + 2 == 4);
                Assert.That(i3, Is.EqualTo(d3));
                Assert.That(2 + 2, Is.Not.EqualTo(5));
                Assert.That(i3, Is.Not.EqualTo(iunequal));
    
                // Inherited syntax
                Expect(2 + 2, EqualTo(4));
                Expect(2 + 2 == 4);
                Expect(i3, EqualTo(d3));
                Expect(2 + 2, Not.EqualTo(5));
                Expect(i3, Not.EqualTo(iunequal));
            }
    
            [Test]
            public void EqualityTestsWithTolerance()
            {
                // CLassic syntax
                Assert.AreEqual(5.0d, 4.99d, 0.05d);
                Assert.AreEqual(5.0f, 4.99f, 0.05f);
    
                // Constraint Syntax
                Assert.That(4.99d, Is.EqualTo(5.0d).Within(0.05d));
                Assert.That(4.0d, Is.Not.EqualTo(5.0d).Within(0.5d));
                Assert.That(4.99f, Is.EqualTo(5.0f).Within(0.05f));
                Assert.That(4.99m, Is.EqualTo(5.0m).Within(0.05m));
                Assert.That(3999999999u, Is.EqualTo(4000000000u).Within(5u));
                Assert.That(499, Is.EqualTo(500).Within(5));
                Assert.That(4999999999L, Is.EqualTo(5000000000L).Within(5L));
                Assert.That(5999999999ul, Is.EqualTo(6000000000ul).Within(5ul));
    
                // Inherited syntax
                Expect(4.99d, EqualTo(5.0d).Within(0.05d));
                Expect(4.0d, Not.EqualTo(5.0d).Within(0.5d));
                Expect(4.99f, EqualTo(5.0f).Within(0.05f));
                Expect(4.99m, EqualTo(5.0m).Within(0.05m));
                Expect(499u, EqualTo(500u).Within(5u));
                Expect(499, EqualTo(500).Within(5));
                Expect(4999999999L, EqualTo(5000000000L).Within(5L));
                Expect(5999999999ul, EqualTo(6000000000ul).Within(5ul));
            }
    
            [Test]
            public void EqualityTestsWithTolerance_MixedFloatAndDouble()
            {
                // Bug Fix 1743844
                Assert.That(2.20492d, Is.EqualTo(2.2d).Within(0.01f),
                    "Double actual, Double expected, Single tolerance");
                Assert.That(2.20492d, Is.EqualTo(2.2f).Within(0.01d),
                    "Double actual, Single expected, Double tolerance");
                Assert.That(2.20492d, Is.EqualTo(2.2f).Within(0.01f),
                    "Double actual, Single expected, Single tolerance");
                Assert.That(2.20492f, Is.EqualTo(2.2f).Within(0.01d),
                    "Single actual, Single expected, Double tolerance");
                Assert.That(2.20492f, Is.EqualTo(2.2d).Within(0.01d),
                    "Single actual, Double expected, Double tolerance");
                Assert.That(2.20492f, Is.EqualTo(2.2d).Within(0.01f),
                    "Single actual, Double expected, Single tolerance");
            }
    
            [Test]
            public void EqualityTestsWithTolerance_MixingTypesGenerally()
            {
                // Extending tolerance to all numeric types
                Assert.That(202d, Is.EqualTo(200d).Within(2),
                    "Double actual, Double expected, int tolerance");
                Assert.That(4.87m, Is.EqualTo(5).Within(.25),
                    "Decimal actual, int expected, Double tolerance");
                Assert.That(4.87m, Is.EqualTo(5ul).Within(1),
                    "Decimal actual, ulong expected, int tolerance");
                Assert.That(487, Is.EqualTo(500).Within(25),
                    "int actual, int expected, int tolerance");
                Assert.That(487u, Is.EqualTo(500).Within(25),
                    "uint actual, int expected, int tolerance");
                Assert.That(487L, Is.EqualTo(500).Within(25),
                    "long actual, int expected, int tolerance");
                Assert.That(487ul, Is.EqualTo(500).Within(25),
                    "ulong actual, int expected, int tolerance");
            }
            #endregion
    
            #region Comparison Tests
            [Test]
            public void ComparisonTests()
            {
                // Classic Syntax
                Assert.Greater(7, 3);
                Assert.GreaterOrEqual(7, 3);
                Assert.GreaterOrEqual(7, 7);
    
                // Constraint Syntax
                Assert.That(7, Is.GreaterThan(3));
                Assert.That(7, Is.GreaterThanOrEqualTo(3));
                Assert.That(7, Is.AtLeast(3));
                Assert.That(7, Is.GreaterThanOrEqualTo(7));
                Assert.That(7, Is.AtLeast(7));
    
                // Inherited syntax
                Expect(7, GreaterThan(3));
                Expect(7, GreaterThanOrEqualTo(3));
                Expect(7, AtLeast(3));
                Expect(7, GreaterThanOrEqualTo(7));
                Expect(7, AtLeast(7));
    
                // Classic syntax
                Assert.Less(3, 7);
                Assert.LessOrEqual(3, 7);
                Assert.LessOrEqual(3, 3);
    
                // Constraint Syntax
                Assert.That(3, Is.LessThan(7));
                Assert.That(3, Is.LessThanOrEqualTo(7));
                Assert.That(3, Is.AtMost(7));
                Assert.That(3, Is.LessThanOrEqualTo(3));
                Assert.That(3, Is.AtMost(3));
    
                // Inherited syntax
                Expect(3, LessThan(7));
                Expect(3, LessThanOrEqualTo(7));
                Expect(3, AtMost(7));
                Expect(3, LessThanOrEqualTo(3));
                Expect(3, AtMost(3));
            }
            #endregion
    
            #region Collection Tests
            [Test]
            public void AllItemsTests()
            {
                object[] ints = new object[] { 1, 2, 3, 4 };
                object[] doubles = new object[] { 0.99, 2.1, 3.0, 4.05 };
                object[] strings = new object[] { "abc", "bad", "cab", "bad", "dad" };
    
                // Classic syntax
                CollectionAssert.AllItemsAreNotNull(ints);
                CollectionAssert.AllItemsAreInstancesOfType(ints, typeof(int));
                CollectionAssert.AllItemsAreInstancesOfType(strings, typeof(string));
                CollectionAssert.AllItemsAreUnique(ints);
    
                // Constraint Syntax
                Assert.That(ints, Is.All.Not.Null);
                Assert.That(ints, Has.None.Null);
                Assert.That(ints, Is.All.InstanceOf(typeof(int)));
                Assert.That(ints, Has.All.InstanceOf(typeof(int)));
                Assert.That(strings, Is.All.InstanceOf(typeof(string)));
                Assert.That(strings, Has.All.InstanceOf(typeof(string)));
                Assert.That(ints, Is.Unique);
                // Only available using new syntax
                Assert.That(strings, Is.Not.Unique);
                Assert.That(ints, Is.All.GreaterThan(0));
                Assert.That(ints, Has.All.GreaterThan(0));
                Assert.That(ints, Has.None.LessThanOrEqualTo(0));
                Assert.That(strings, Is.All.Contains("a"));
                Assert.That(strings, Has.All.Contains("a"));
                Assert.That(strings, Has.Some.StartsWith("ba"));
                Assert.That(strings, Has.Some.Property("Length").EqualTo(3));
                Assert.That(strings, Has.Some.StartsWith("BA").IgnoreCase);
                Assert.That(doubles, Has.Some.EqualTo(1.0).Within(.05));
    
                // Inherited syntax
                Expect(ints, All.Not.Null);
                Expect(ints, None.Null);
                Expect(ints, All.InstanceOf(typeof(int)));
                Expect(strings, All.InstanceOf(typeof(string)));
                Expect(ints, Unique);
                // Only available using new syntax
                Expect(strings, Not.Unique);
                Expect(ints, All.GreaterThan(0));
                Expect(ints, None.LessThanOrEqualTo(0));
                Expect(strings, All.Contains("a"));
                Expect(strings, Some.StartsWith("ba"));
                Expect(strings, Some.StartsWith("BA").IgnoreCase);
                Expect(doubles, Some.EqualTo(1.0).Within(.05));
            }
    
            [Test]
            public void SomeItemTests()
            {
                object[] mixed = new object[] { 1, 2, "3", null, "four", 100 };
                object[] strings = new object[] { "abc", "bad", "cab", "bad", "dad" };
    
                // Not available using the classic syntax
    
                // Constraint Syntax
                Assert.That(mixed, Has.Some.Null);
                Assert.That(mixed, Has.Some.InstanceOf(typeof(int)));
                Assert.That(mixed, Has.Some.InstanceOf(typeof(string)));
                Assert.That(strings, Has.Some.StartsWith("ba"));
                Assert.That(strings, Has.Some.Not.StartsWith("ba"));
    
                // Inherited syntax
                Expect(mixed, Some.Null);
                Expect(mixed, Some.InstanceOf(typeof(int)));
                Expect(mixed, Some.InstanceOf(typeof(string)));
                Expect(strings, Some.StartsWith("ba"));
                Expect(strings, Some.Not.StartsWith("ba"));
            }
    
            [Test]
            public void NoItemTests()
            {
                object[] ints = new object[] { 1, 2, 3, 4, 5 };
                object[] strings = new object[] { "abc", "bad", "cab", "bad", "dad" };
    
                // Not available using the classic syntax
    
                // Constraint Syntax
                Assert.That(ints, Has.None.Null);
                Assert.That(ints, Has.None.InstanceOf(typeof(string)));
                Assert.That(ints, Has.None.GreaterThan(99));
                Assert.That(strings, Has.None.StartsWith("qu"));
    
                // Inherited syntax
                Expect(ints, None.Null);
                Expect(ints, None.InstanceOf(typeof(string)));
                Expect(ints, None.GreaterThan(99));
                Expect(strings, None.StartsWith("qu"));
            }
    
            [Test]
            public void CollectionContainsTests()
            {
                int[] iarray = new int[] { 1, 2, 3 };
                string[] sarray = new string[] { "a", "b", "c" };
    
                // Classic syntax
                Assert.Contains(3, iarray);
                Assert.Contains("b", sarray);
                CollectionAssert.Contains(iarray, 3);
                CollectionAssert.Contains(sarray, "b");
                CollectionAssert.DoesNotContain(sarray, "x");
                // Showing that Contains uses NUnit equality
                CollectionAssert.Contains(iarray, 1.0d);
    
                // Constraint Syntax
                Assert.That(iarray, Has.Member(3));
                Assert.That(sarray, Has.Member("b"));
                Assert.That(sarray, Has.No.Member("x"));
                // Showing that Contains uses NUnit equality
                Assert.That(iarray, Has.Member(1.0d));
    
                // Only available using the new syntax
                // Note that EqualTo and SameAs do NOT give
                // identical results to Contains because 
                // Contains uses Object.Equals()
                Assert.That(iarray, Has.Some.EqualTo(3));
                Assert.That(iarray, Has.Member(3));
                Assert.That(sarray, Has.Some.EqualTo("b"));
                Assert.That(sarray, Has.None.EqualTo("x"));
                Assert.That(iarray, Has.None.SameAs(1.0d));
                Assert.That(iarray, Has.All.LessThan(10));
                Assert.That(sarray, Has.All.Length.EqualTo(1));
                Assert.That(sarray, Has.None.Property("Length").GreaterThan(3));
    
                // Inherited syntax
                Expect(iarray, Contains(3));
                Expect(sarray, Contains("b"));
                Expect(sarray, Not.Contains("x"));
    
                // Only available using new syntax
                // Note that EqualTo and SameAs do NOT give
                // identical results to Contains because 
                // Contains uses Object.Equals()
                Expect(iarray, Some.EqualTo(3));
                Expect(sarray, Some.EqualTo("b"));
                Expect(sarray, None.EqualTo("x"));
                Expect(iarray, All.LessThan(10));
                Expect(sarray, All.Length.EqualTo(1));
                Expect(sarray, None.Property("Length").GreaterThan(3));
            }
    
            [Test]
            public void CollectionEquivalenceTests()
            {
                int[] ints1to5 = new int[] { 1, 2, 3, 4, 5 };
                int[] twothrees = new int[] { 1, 2, 3, 3, 4, 5 };
                int[] twofours = new int[] { 1, 2, 3, 4, 4, 5 };
    
                // Classic syntax
                CollectionAssert.AreEquivalent(new int[] { 2, 1, 4, 3, 5 }, ints1to5);
                CollectionAssert.AreNotEquivalent(new int[] { 2, 2, 4, 3, 5 }, ints1to5);
                CollectionAssert.AreNotEquivalent(new int[] { 2, 4, 3, 5 }, ints1to5);
                CollectionAssert.AreNotEquivalent(new int[] { 2, 2, 1, 1, 4, 3, 5 }, ints1to5);
                CollectionAssert.AreNotEquivalent(twothrees, twofours);
    
                // Constraint Syntax
                Assert.That(new int[] { 2, 1, 4, 3, 5 }, Is.EquivalentTo(ints1to5));
                Assert.That(new int[] { 2, 2, 4, 3, 5 }, Is.Not.EquivalentTo(ints1to5));
                Assert.That(new int[] { 2, 4, 3, 5 }, Is.Not.EquivalentTo(ints1to5));
                Assert.That(new int[] { 2, 2, 1, 1, 4, 3, 5 }, Is.Not.EquivalentTo(ints1to5));
    
                // Inherited syntax
                Expect(new int[] { 2, 1, 4, 3, 5 }, EquivalentTo(ints1to5));
                Expect(new int[] { 2, 2, 4, 3, 5 }, Not.EquivalentTo(ints1to5));
                Expect(new int[] { 2, 4, 3, 5 }, Not.EquivalentTo(ints1to5));
                Expect(new int[] { 2, 2, 1, 1, 4, 3, 5 }, Not.EquivalentTo(ints1to5));
            }
    
            [Test]
            public void SubsetTests()
            {
                int[] ints1to5 = new int[] { 1, 2, 3, 4, 5 };
    
                // Classic syntax
                CollectionAssert.IsSubsetOf(new int[] { 1, 3, 5 }, ints1to5);
                CollectionAssert.IsSubsetOf(new int[] { 1, 2, 3, 4, 5 }, ints1to5);
                CollectionAssert.IsNotSubsetOf(new int[] { 2, 4, 6 }, ints1to5);
                CollectionAssert.IsNotSubsetOf(new int[] { 1, 2, 2, 2, 5 }, ints1to5);
    
                // Constraint Syntax
                Assert.That(new int[] { 1, 3, 5 }, Is.SubsetOf(ints1to5));
                Assert.That(new int[] { 1, 2, 3, 4, 5 }, Is.SubsetOf(ints1to5));
                Assert.That(new int[] { 2, 4, 6 }, Is.Not.SubsetOf(ints1to5));
    
                // Inherited syntax
                Expect(new int[] { 1, 3, 5 }, SubsetOf(ints1to5));
                Expect(new int[] { 1, 2, 3, 4, 5 }, SubsetOf(ints1to5));
                Expect(new int[] { 2, 4, 6 }, Not.SubsetOf(ints1to5));
            }
            #endregion
    
            #region Property Tests
            [Test]
            public void PropertyTests()
            {
                string[] array = { "abc", "bca", "xyz", "qrs" };
                string[] array2 = { "a", "ab", "abc" };
                ArrayList list = new ArrayList(array);
    
                // Not available using the classic syntax
    
                // Constraint Syntax
                Assert.That(list, Has.Property("Count"));
                Assert.That(list, Has.No.Property("Length"));
    
                Assert.That("Hello", Has.Length.EqualTo(5));
                Assert.That("Hello", Has.Length.LessThan(10));
                Assert.That("Hello", Has.Property("Length").EqualTo(5));
                Assert.That("Hello", Has.Property("Length").GreaterThan(3));
    
                Assert.That(array, Has.Property("Length").EqualTo(4));
                Assert.That(array, Has.Length.EqualTo(4));
                Assert.That(array, Has.Property("Length").LessThan(10));
    
                Assert.That(array, Has.All.Property("Length").EqualTo(3));
                Assert.That(array, Has.All.Length.EqualTo(3));
                Assert.That(array, Is.All.Length.EqualTo(3));
                Assert.That(array, Has.All.Property("Length").EqualTo(3));
                Assert.That(array, Is.All.Property("Length").EqualTo(3));
    
                Assert.That(array2, Has.Some.Property("Length").EqualTo(2));
                Assert.That(array2, Has.Some.Length.EqualTo(2));
                Assert.That(array2, Has.Some.Property("Length").GreaterThan(2));
    
                Assert.That(array2, Is.Not.Property("Length").EqualTo(4));
                Assert.That(array2, Is.Not.Length.EqualTo(4));
                Assert.That(array2, Has.No.Property("Length").GreaterThan(3));
    
                Assert.That(List.Map(array2).Property("Length"), Is.EqualTo(new int[] { 1, 2, 3 }));
                Assert.That(List.Map(array2).Property("Length"), Is.EquivalentTo(new int[] { 3, 2, 1 }));
                Assert.That(List.Map(array2).Property("Length"), Is.SubsetOf(new int[] { 1, 2, 3, 4, 5 }));
                Assert.That(List.Map(array2).Property("Length"), Is.Unique);
    
                Assert.That(list, Has.Count.EqualTo(4));
    
                // Inherited syntax
                Expect(list, Property("Count"));
                Expect(list, Not.Property("Nada"));
    
                Expect("Hello", Length.EqualTo(5));
                Expect("Hello", Property("Length").EqualTo(5));
                Expect("Hello", Property("Length").GreaterThan(0));
    
                Expect(array, Property("Length").EqualTo(4));
                Expect(array, Length.EqualTo(4));
                Expect(array, Property("Length").LessThan(10));
    
                Expect(array, All.Length.EqualTo(3));
                Expect(array, All.Property("Length").EqualTo(3));
    
                Expect(array2, Some.Property("Length").EqualTo(2));
                Expect(array2, Some.Length.EqualTo(2));
                Expect(array2, Some.Property("Length").GreaterThan(2));
    
                Expect(array2, None.Property("Length").EqualTo(4));
                Expect(array2, None.Length.EqualTo(4));
                Expect(array2, None.Property("Length").GreaterThan(3));
    
                Expect(Map(array2).Property("Length"), EqualTo(new int[] { 1, 2, 3 }));
                Expect(Map(array2).Property("Length"), EquivalentTo(new int[] { 3, 2, 1 }));
                Expect(Map(array2).Property("Length"), SubsetOf(new int[] { 1, 2, 3, 4, 5 }));
                Expect(Map(array2).Property("Length"), Unique);
    
                Expect(list, Count.EqualTo(4));
    
            }
            #endregion
    
            #region Not Tests
            [Test]
            public void NotTests()
            {
                // Not available using the classic syntax
    
                // Constraint Syntax
                Assert.That(42, Is.Not.Null);
                Assert.That(42, Is.Not.True);
                Assert.That(42, Is.Not.False);
                Assert.That(2.5, Is.Not.NaN);
                Assert.That(2 + 2, Is.Not.EqualTo(3));
                Assert.That(2 + 2, Is.Not.Not.EqualTo(4));
                Assert.That(2 + 2, Is.Not.Not.Not.EqualTo(5));
    
                // Inherited syntax
                Expect(42, Not.Null);
                Expect(42, Not.True);
                Expect(42, Not.False);
                Expect(2.5, Not.NaN);
                Expect(2 + 2, Not.EqualTo(3));
                Expect(2 + 2, Not.Not.EqualTo(4));
                Expect(2 + 2, Not.Not.Not.EqualTo(5));
            }
            #endregion
    
            #region Operator Tests
            [Test]
            public void NotOperator()
            {
                // The ! operator is only available in the new syntax
                Assert.That(42, !Is.Null);
                // Inherited syntax
                Expect(42, !Null);
            }
    
            [Test]
            public void AndOperator()
            {
                // The & operator is only available in the new syntax
                Assert.That(7, Is.GreaterThan(5) & Is.LessThan(10));
                // Inherited syntax
                Expect(7, GreaterThan(5) & LessThan(10));
            }
    
            [Test]
            public void OrOperator()
            {
                // The | operator is only available in the new syntax
                Assert.That(3, Is.LessThan(5) | Is.GreaterThan(10));
                Expect(3, LessThan(5) | GreaterThan(10));
            }
    
            [Test]
            public void ComplexTests()
            {
                Assert.That(7, Is.Not.Null & Is.Not.LessThan(5) & Is.Not.GreaterThan(10));
                Expect(7, Not.Null & Not.LessThan(5) & Not.GreaterThan(10));
    
                Assert.That(7, !Is.Null & !Is.LessThan(5) & !Is.GreaterThan(10));
                Expect(7, !Null & !LessThan(5) & !GreaterThan(10));
    
                // No longer works at all under 3.0
                // TODO: Evaluate why we wanted to use null in this setting in the first place
    #if false
                    // TODO: Remove #if when mono compiler can handle null
    #if MONO
                    Constraint x = null;
                    Assert.That(7, !x & !Is.LessThan(5) & !Is.GreaterThan(10));
                    Expect(7, !x & !LessThan(5) & !GreaterThan(10));
    #else
                    Assert.That(7, !(Constraint)null & !Is.LessThan(5) & !Is.GreaterThan(10));
                    Expect(7, !(Constraint)null & !LessThan(5) & !GreaterThan(10));
    #endif
    #endif
            }
            #endregion
    
            #region Invalid Code Tests
            // This method contains assertions that should not compile
            // You can check by uncommenting it.
            //public void WillNotCompile()
            //{
            //    Assert.That(42, Is.Not);
            //    Assert.That(42, Is.All);
            //    Assert.That(42, Is.Null.Not);
            //    Assert.That(42, Is.Not.Null.GreaterThan(10));
            //    Assert.That(42, Is.GreaterThan(10).LessThan(99));
    
            //    object[] c = new object[0];
            //    Assert.That(c, Is.Null.All);
            //    Assert.That(c, Is.Not.All);
            //    Assert.That(c, Is.All.Not);
            //}
            #endregion
        }
    
        #endregion
    

    单元测试参考资料

    相关文章

      网友评论

      本文标题:走进 .Net 单元测试

      本文链接:https://www.haomeiwen.com/subject/vujtuttx.html