.net 企业网站源码下载,韩国优秀网站设计,重庆装饰公司,外链提交转载#xff1a;http://tech.sina.com.cn/s/2009-07-17/1129988785.shtml 单元测试基础知识 单元测试是开发者编写的一小段代码#xff0c;用于检验被测代码的一个很小的、很明确的功能是否正确。通常而言#xff0c;一个单元测试是用于判断某个特定条件(或者场景)下某个特定…转载http://tech.sina.com.cn/s/2009-07-17/1129988785.shtml 单元测试基础知识 单元测试是开发者编写的一小段代码用于检验被测代码的一个很小的、很明确的功能是否正确。通常而言一个单元测试是用于判断某个特定条件(或者场景)下某个特定函数的行为。例如你可能把一个很大的值放入一个有序list 中去然后确认该值出现在list 的尾部。或者你可能会从字符串中删除匹配某种模式的字符然后确认字符串确实不再包含这些字符了。 执行单元测试是为了证明某段代码的行为确实和开发者所期望的一致。 当编写项目的时刻如果我们假设底层的代码是正确无误的那么先是高层代码中使用了底层代码;然后这些高层代码又被更高层的代码所使用如此往复。当基本的底层代码不再可靠时那么必需的改动就无法只局限在底层。虽然你可以修正底层的问题但是这些对底层代码的修改必然会影响到高层代码。于是一个对底层代码的修正可能会导致对几乎所有代码的一连串改动从而使修改越来越多也越来越复杂。从而使整个项目也以失败告终。 而单元测试的核心内涵这个简单有效的技术就是为了令代码变得更加完美。 NUnit介绍 NUnit 是一个免费开源的产品它提供了一套测试框架和一个测试运行程序(test runner)。 注意test tunner 知道如何寻找具有 [TestFixture] 属性的类和类中的 [Test] 方法。 如何安装 NUnit 在官网下载NUnit当前最新的版是2.4.8我下的是NUnit-2.4.8-net-2.0.zip。 NUnit第一个演示 我们用Visual Studio 2008新建一个NUnit项目 为了便于演示我们把默认的Program.cs改成Calculator.cs在Calculator类里我们实现简单的加减乘除四个方法。完整代码如下 using System; namespace NUnitTest { public class Calculator { /// summary /// 加法 /// /summary /// param namea/param /// param nameb/param /// returns/returns public int Add(int a,int b) { return a b; } /// summary /// 减法 /// /summary /// param namea/param /// param nameb/param /// returns/returns public int Minus(int a, int b) { return a - b; } /// summary /// 乘法 /// /summary /// param namea/param /// param nameb/param /// returns/returns public int Multiply(int a, int b) { return a * b; } /// summary /// 除法 /// /summary /// param namea/param /// param nameb/param /// returns/returns public int Divide(int a, int b) { return a / b; } static void Main(string[] args) { Calculator cal new Calculator(); int result cal.Add(2,3); Console.WriteLine(result); Console.ReadKey(true); } } } 如果没有单元测试我们普通的测试方法就像是Main方法一样这样的测试是一个很邪恶的测试方法花时间且很难得到我们 想要的结果。 那么我们应该如何来用NUnit做单元测试呢? 我们再新建一个项目 为这个NUnitTestTest引用“NUnitTest项目”和“nunit.framewor类库”。我们再新建一个测试类命名为“CalculatorTest.cs”。并键入如下代码 using System; using NUnit.Framework; using NUnitTest; namespace NUnitTestTest { [TestFixture] public class CalculatorTest { [Test] public void TestAdd() { Calculator cal new Calculator(); int expected 5; int actual cal.Add(2, 3); Assert.AreEqual(expected, actual); } } } 这就是一个简单的单元测试方法了。首先我们使用using NUnit.Framework和using NUnitTest因为接下来的代码需要用到这两个命名空间。在这里我们要注意几点NUnit测试用的类前面一定要加上[TestFixture]以表示这是NUnit测试类测试方法一定是public的且没有返回值。这里的TestFixture和Test都是NUnit的Attribute下表给出了NUnit常用的Attribute Assert.AreEqual是断言在测试框架中断言是单元测试的核心我们在测试中要对其程序断言。如果某个断言失败方法的调用不会返回值并且会报告一个错误。如果一个测试包含多个断言那些紧跟失败断言的那些断言都不会执行因此每个测试方法最好只有一个断言。 NUnit.Framework.Assert有23个重载方法大部分的情况它都有考虑到当然不排除需要自己写一个复杂的断言方法。 上面的代码中int expected 5;是指我们期望程序执行的结果是5int actual cal.Add(2, 3);则执行Calculator.Add方法得到实际的值。 顺便说一下CalculatorTest(类名)还有TestAdd(方法名)并不是一定要这样写你可以自由的命名你的名称不过为了让你的代码可读性更好请遵循一个命名规范这个规范可以是公司定的也可以是网上主流的命名规则。 对Add()方法的单元测试代码已经完成了接下来我们运行下载解压后文件夹中的nunit.exe程序界面如图 打开对话File/Open Project...对话框或者按Ctrl O把第二个单元测试项目NUnitTestTest生成的NUnitTestTest.dll加载进来 我们点右边的Run按钮执行单元测试 太棒了绿色通过Keep the bar green to keep the code clean. 一个简单的单元测试过程就是这样的。 我们再为除法写一个单元测试方法 [Test] public void TestDivide() { Calculator cal new Calculator(); int expected 5; int actual cal.Divide(25, 5); Assert.AreEqual(expected, actual); } 重新生成NUnitTestTest项目NUnit会自动把TestDivide方法加进去。 再点Run通过测试。大家都知道除法中除数不能为0如果这里除数是0呢?会有什么样的结果? [Test] public void TestDivide() { Calculator cal new Calculator(); int expected 5; int actual cal.Divide(25, 0); Assert.AreEqual(expected, actual); } 生成项目并重新运行单元测试 测试没有通过 “NUnitTestTest.CalculatorTest.TestDivide:System.DivideByZeroException : 试图除以零。”这时我们要返回到Calculator类中修改Divide方法使之除数为0时返回其它的值。 NUnit第一个简单示例就先到这里在NUnit的官网也有简单教程大家可以看看。 在单元测试中我们在做正面的测试的同时也要做一些反面测试这样才能让我们的代码更健壮。 在Visual Studio 2008 中打开上一章的示例Calculator类有4个最简单的方法加、减、乘、除。CalculatorTest类中的四个方法是Calculator类四个方法的单元测试。 [TestFixture] public class CalculatorTest ...{ [Test] public void TestAdd() ...{ Calculator cal new Calculator(); int expected 5; int actual cal.Add(2, 3); Assert.AreEqual(expected, actual); } [Test] public void TestMinus() ...{ Calculator cal new Calculator(); int expected 5; int actual cal.Minus(10, 5); Assert.AreEqual(expected, actual); } [Test] public void TestMultiply() ...{ Calculator cal new Calculator(); int expected 5; int actual cal.Multiply(1, 5); Assert.AreEqual(expected, actual); } [Test] public void TestDivide() ...{ Calculator cal new Calculator(); int expected 5; int actual cal.Divide(25, 5); Assert.AreEqual(expected, actual); } } 这里一定要注意TestAdd()、TestMinus()、TestMultiply()和TestDivide()方法没有任何关系也就是说单元测试中所有的测试方法都是独立的。各个方法之间没有依赖性删除任何一个单元测试方法对其它的测试不会有任何影响。 上一章中我们已经介绍了[TestFixture]和[Test]现在我们为这个类新增一个方法。 [SetUp] public void InitMethod() { Console.WriteLine(Initialization method); } 重新生成项目再运行NUnit选中CalculatorTest进行单元测试 切换到NUnit的Console.Out中我们看到Initialization method出现了4次如果只选中一个测试方法 我们看到这时只出现一次的Initialization method。[SetUp]的意思就是指在运行每个测试方法前执行它。相应的有开始必然有结束[TearDown]是指在每个测试方法结束后运行。 我们再新增一个方法 [TearDown] public void FinalizeMethod() { Console.WriteLine(Finalize method); } 再来看运行NUnit的结果 知道了[SetUp]和[TearDown]后我们就可以改写这个单元测试类了。 请[TestFixture] public class CalculatorTest ...{ private Calculator cal; private int a, b, expected, actual; [SetUp] public void InitMethod() ...{ cal new Calculator(); a 10; b 2; } [Test] public void TestAdd() ...{ expected 12; actual cal.Add(a, b); Assert.AreEqual(expected, actual); } [Test] public void TestMinus() ...{ expected 8; actual cal.Minus(a, b); Assert.AreEqual(expected, actual); } [Test] public void TestMultiply() ...{ expected 20; actual cal.Multiply(a, b); Assert.AreEqual(expected, actual); } [Test] public void TestDivide() ...{ expected 5; actual cal.Divide(a, b); Assert.AreEqual(expected, actual); } } 因为运行每个测试方法之前都会运行InitMethod()方法所以每次都会初始化使第一个操作数为10第二个操作数为2。在[SetUp]中初始化了的资源我们就可以在[TearDown]里销毁释放。 这里也许有人会问如果我的项目很大每个测试方法都需要连接数据库在每个方法执行的时候进行连接再释放这样是不是太耗资源太慢了能不能在一个单元测试类实例化的时候就运行一个指定的方法呢? 这是可以的。在NUnit中我们使用[TestFixtureSetUp]和[TestFixtureTearDown]就可以实现这样的功能。[TestFixtureSetUp]是指在这个测试类的整个生命周期中它在所有的测试方法之前运行一次而[TestFixtureTearDown]是在所有的测试方法都结束时运行。 这里要注意的[TestFixtureSetUp]与构造函数是不一样的它标识的方法迟于构造函数运行。我们再对这个测试类进行重构 [TestFixture] public class CalculatorTest ...{ private Calculator cal; private int a, b, expected, actual; public CalculatorTest() ...{ Console.WriteLine(执行构造函数); } [TestFixtureSetUp] public void InitClass() ...{ Console.WriteLine(执行TestFixtureSetUp); cal new Calculator(); a 10; b 2; } [TestFixtureTearDown] public void FinalizeClass() ...{ Console.WriteLine(执行TestFixtureTearDown); } [SetUp] public void InitMethod() ...{ Console.WriteLine(执行SetUp); } [TearDown] public void FinalizeMethod() ...{ Console.WriteLine(执行TearDown); a 10; b 2; } [Test] public void TestAdd() ...{ Console.WriteLine(TestAdd() Begin); expected 12; actual cal.Add(a, b); Assert.AreEqual(expected, actual); Console.WriteLine(TestAdd() End); } [Test] public void TestMinus() ...{ Console.WriteLine(TestMinus() Begin); expected 8; actual cal.Minus(a, b); Assert.AreEqual(expected, actual); Console.WriteLine(TestMinus() End); } [Test] public void TestMultiply() ...{ Console.WriteLine(TestMultiply() Begin); expected 20; actual cal.Multiply(a, b); Assert.AreEqual(expected, actual); Console.WriteLine(TestMultiply() End); } [Test] public void TestDivide() ...{ Console.WriteLine(TestDivide() Begin); expected 5; actual cal.Divide(a, b); Assert.AreEqual(expected, actual); Console.WriteLine(TestDivide() End); } } 在NUnit中我们可以很清楚地看到这个类的执行顺序 假如我们的测试项目中有使用到数据库就可以把数据库连接写在[TestFixtureSetUp]中把释放的代码写在[TestFixtureTearDown]中。 我相信现在大家对NUnit的这4个属性都应该有一个直观的认识了吧。都是4个很简单的属性但是在使用中用处却是非常大的。 接下来再为大家介绍几个常用的属性。 现在的测试中我们有4个测试方法但是如果我们想让其中的一个测试方法不在NUnit中显示怎么办呢?不是注释大家不要想歪了注释大家都知道。要想让一个测试方法不在NUnit中显示也不运行我们应该使用[Ignore]属性。看看把TestAdd()添加[Ignore]属性后会是什么样子 [Test] [Ignore] public void TestAdd() { Console.WriteLine(TestAdd() Begin); expected 12; actual cal.Add(a, b); Assert.AreEqual(expected, actual); Console.WriteLine(TestAdd() End); } 现在有了一个新的颜色了——黄色。它是指被忽略的方法。当然你在项目中出现最多的肯定是绿色。在NUnit中我们可以用[Ignore]的重载方法[Ignore(忽略原因)]来定义忽略原因。 NUnit有一个与[Ignore]类似的属性[Explicit]它是指只有在NUnit中被明确的指定时才运行否则不运行。有点拗口我们来看例子。改写TestMinus方法 [Test,Explicit] public void TestMinus() { Console.WriteLine(TestMinus() Begin); expected 8; actual cal.Minus(a, b); Assert.AreEqual(expected, actual); Console.WriteLine(TestMinus() End); } 这里 [Test,Explicit] 和 [Test] [Explicit] 是完全一样的。 我们看它的截图 TestMinus是灰色的运行的Cases有2个一个被忽略。而当我们选中TestMinus时 这个测试运行了。 再给大家介绍一个分类属性[Category(string name)]利用这个分类属性我们可以为每个方法定义类别。 [Test, Ignore(Ignore), Category(Category A)] public void TestAdd() ...{ Console.WriteLine(TestAdd() Begin); expected 12; actual cal.Add(a, b); Assert.AreEqual(expected, actual); Console.WriteLine(TestAdd() End); } [Test, Category(Category B)] [Explicit] public void TestMinus() ...{ Console.WriteLine(TestMinus() Begin); expected 8; actual cal.Minus(a, b); Assert.AreEqual(expected, actual); Console.WriteLine(TestMinus() End); } [Test, Category(Category A)] public void TestMultiply() ...{ Console.WriteLine(TestMultiply() Begin); expected 20; actual cal.Multiply(a, b); Assert.AreEqual(expected, actual); Console.WriteLine(TestMultiply() End); } [Test, Category(Category B)] public void TestDivide() ...{ Console.WriteLine(TestDivide() Begin); expected 5; actual cal.Divide(a, b); Assert.AreEqual(expected, actual); Console.WriteLine(TestDivide() End); } 重新生成项目在NUnit中我们可以看到 这里有我们定义的两个分类我们选中Category A切换回Tests点Run我们看 只测试了我们设置的Category A的一个方法另一个方法是因为我们设置了[Ignore]所以没有执行测试。 好到这里我们已经把NUnit主要的属性学完了接下来的章节我们将从实例出发学习NUnit。转载于:https://www.cnblogs.com/zhaox583132460/p/3442903.html