单元测试框架NUnit 之 Extensibility 例子

首先定义一个自定义的attribute

using System;



namespace NUnit.Core.Extensions

{

	/// <summary>

	/// 这个自定义特性只是用来标记类,Nunit发现这个标记的类会调用我们插件的逻辑来构建测试类

	/// </summary>

	[AttributeUsage(AttributeTargets.Class, AllowMultiple=false)]

	public sealed class SampleFixtureExtensionAttribute : Attribute

	{

	}

}

下面是一个插件的主要逻辑:

using System;

using NUnit.Core.Builders;

using NUnit.Core.Extensibility;



namespace NUnit.Core.Extensions

{

        //  此处应用NUnitAddin特性

	[NUnitAddin(Description="这个插件的就是包装了NUnitTestFixture,对SetUp 和 TearDown 的逻辑进行改变。 ")]

	public class SampleFixtureExtensionBuilder : ISuiteBuilder, IAddin

	{	

		#region ISuiteBuilder Members

		public bool CanBuildFrom(Type type)

		{

			return Reflect.HasAttribute( type, "NUnit.Core.Extensions.SampleFixtureExtensionAttribute", false );

		}



		public Test BuildFrom(Type type)

		{

            if (CanBuildFrom(type))

            {

                return new SampleFixtureExtension(type);

            }

			return null;

		}

		#endregion



		#region IAddin Members

		public bool Install(IExtensionHost host)

		{

			IExtensionPoint suiteBuilders = host.GetExtensionPoint( "SuiteBuilders" );

			if ( suiteBuilders == null )

				return false;



			suiteBuilders.Install( this );

			return true;

		}

		#endregion

	}

}

我们可以看到这个插件实现了ISuiteBuilder接口,是对SuiteBuilder扩展点进行的扩展,扩展点的主要作用就是从类构建测试类的。当Nunit启动时,会扫描addins目录,加载所有程序集,扫描其中的所有公共类,如果实现了NUnitAddin,就会把该类型存储进一个数组中。而当core初始化时,会先加载扩展点和内建的扩展,然后遍历之前的数组,构造这个类的实例,对我们的例子就是SampleFixtureExtensionBuilder 类,转型为IAddIn调用Install并把当前host做为参数传入。如上文所述,被扩展的host实现了IExtensionHost接口,我们的install方法内部就用它的GetExtensionPoint方法获取扩展点对象,此例中获取SuiteBuilders,获取扩展点,它们实现了IExtensionPoint或IExtensionPoint2接口,调用扩展点对象的Install方法,把扩展本身传入。所有扩展点的Install方法都是继承自ExtensionPoint的,因此所有的扩展点的install方法逻辑都是一样的,只不过此处采用的模板模式,会调用各个扩展点类的检查,是不是合适的扩展,然后加入了扩展集合。

这些还是不够的,我们想把以自定义特性SampleFixtureExtensionAttribute 的类构建成什么样的测试类呢?

using System;



namespace NUnit.Core.Extensions

{

	/// <summary>

	/// 此类继承自NUnitTestFixture,对可以扩展的方法进行重写

	/// </summary>

	class SampleFixtureExtension : NUnitTestFixture

	{

		public SampleFixtureExtension( Type fixtureType ) 

			: base( fixtureType )

		{

                        //  这里不需要做什么,因为我们使用了基类的构造



		}

                // 下面是我们重写了基类的方法

		protected override void DoOneTimeSetUp(TestResult suiteResult)

		{

			Console.WriteLine( "Extended Fixture SetUp called" );

			base.DoOneTimeSetUp (suiteResult);

		}



		protected override void DoOneTimeTearDown(TestResult suiteResult)

		{

			base.DoOneTimeTearDown (suiteResult);

			Console.WriteLine( "Extended Fixture TearDown called" );

		}

	}

}

好,扩展大功告成,再来看我们扩展里的ISuiteBuilder 成员中的BuildFrom方法,它会把符合条件的类构建成SampleFixtureExtension 类型的类,至于是怎么构建的,这个我们调用了基类NUnitTestFixture的构造方法。

下面建一个测试项目引用我们的插件项目生成的dll,新建一个测试类,来测试下我们的插件。

using System;

using NUnit.Framework;

using NUnit.Core.Extensions;



namespace NUnit.Extensions.Tests

{

	/// <summary>

	/// Test class that demonstrates SampleFixtureExtension

	/// </summary>

	[SampleFixtureExtension]

	public class SampleFixtureExtensionTests

	{

		[TestFixtureSetUp]

		public void SetUpTests()

		{

			Console.WriteLine( "TestFixtureSetUp called" );

		}



		[TestFixtureTearDown]

		public void FixtureTearDown()

		{

			Console.WriteLine( "TestFixtureTearDown called" );

		}



		[Test]

		public void SomeTest()

		{

            Assert.IsEmpty("");

		}



		[Test]

		public void AnotherTest()

		{

            Assert.IsNaN(5d);

		}

	}

}

编译测试项目。

 

把编译好的插件的dll复制一份到nunit安装目录的addins目录下,运行nunit.exe,这时点击Tools菜单的addin,我们可以看到插件列表,这里可以看到我们的插件。然后添加你的测试项目进来,run。在输出的Text output选项卡中,可以看到:

Extended Fixture SetUp called
TestFixtureSetUp called
TestFixtureTearDown called
Extended Fixture TearDown called

可知,我们插件已经正常工作了,我们新加了nunit本身所没有的行为,插件的目的也就达到了。

 

但是,为什么我们测试类另两个普通的测试方法没有运行呢?你可以看一下nunit界面测试树上,根本就没有这两个方法的结点?我们知道我们构建的测试类继承自NUnitTestFixture的,这个类的构造函数只会处理其中标记为setup和teardown方法,因此其它两个普通的方法根本没被构建,因此测试的树上就没有这两个方法的结点,更不要说运行了。

 

如果

如果我们把测试类上的SampleFixtureExtension标记移除掉,结果如何呢?

移除之后重新编译,再来看界面的测试树,SomeTest和AnotherTest的结点已经出现了:由此我们可以知道nunit监视测试项目的dll,当它改变时,就会构建测试。此时这个测试类只是一个变通的测试类,这两个方法也被构建了。Run,结果??

有一个错误,在Errors or failures选项卡上,我们得到这样的信息:

NUnit.Extensions.Tests.SampleFixtureExtensionTests.AnotherTest:
  Expected: NaN
  But was:  5.0d

这个断言失败了,正是我们想的结果。

在Text output选项卡,有这样的信息:

TestFixtureSetUp called
***** NUnit.Extensions.Tests.SampleFixtureExtensionTests.SomeTest
TestFixtureTearDown called

这就是最简单的测试行为了。

 

《完》

你可能感兴趣的:(单元测试)