InfoQ

新闻

xUnit.net:下一代单元测试框架?

作者 Hartmut Wilms 译者 郭晓刚 发布于 2007年9月27日 上午1时9分

社区
.NET,
Agile
主题
敏捷技术,
质量交付,
单元测试
标签
NUnit,
测试,
测试驱动开发

NUnit的创造者Jim Newkirk公布了一个新的单元测试框架,叫做xUnit.net。这个以NUnit接班人自许的新框架打算消除NUnit的错误和缺点,并打算在框架中加入一些最佳实践和扩展能力。

Jim Newkirk和Brad Wilson这两位xUnit.net的创造者,从NUnit和其他单元测试框架的经验中总结出来以下改进:

  • 为每个测试方法产生一个对象实例
  • 取消了[SetUp]和[TearDown]
  • 取消了[ExpectedException]
  • 类似于Aspect的功能
  • 减少了自定义属性(Attribute)的数目
  • 采用泛型
  • 匿名委托
  • 可扩展的断言
  • 可扩展的测试方法
  • 可扩展的测试类

xUnit.net减少了属性(Attributes)的数量,属性被用来控制测试和测试的执行过程。其中有个 [Test]属性用来标出测试方法。跟NUnit、MbUnitMSTest不同,测试类并没有任何标志。xUnit.net直接在程序集中查找所有公开类的全部公开测试方法。[SetUp]和[TearDown]已经被抛弃,因为它们一般被认为是坏的实践:

xUnit.net团队觉得每项测试分别执行setup和teardown会产生难以理解与除错的测试代码,并且常常导致每一项测试执行之前都要运行一些不必要的代码。

Jim Newkirk曾经在博客上撰文说明为何不应在NUnit中使用SetUp和TearDown

我对SetUp的不满来自两个方面。第一也是主要的问题是,在我阅读每个测试的时候,我都不得不瞥一眼BeforeTest(),看看在测试中用到的那些值。如果有TearDown方法的话就更糟,这下我要看3个方法。第二个问题是BeforeTest()为所有的测试初始化成员变量,这会让BeforeTest()复杂化而且违反了单一职责原则。

原先[ExpectedException]属性被用来声明希望测试代码抛出的异常,它已被Assert.Throws断言取代。测试集(TestFixture)由ITestFixture接口标出,接口里面有两个方法:BeforeAllTests()和AfterAllTests()。测试超时和暂时跳过某些测试是通过[Test]属性的参数来实现的,并没有单独为此定义属性。MbUnit里面非常受欢迎的[RowTest]和[Row]测试模式也被包括了进来,由[Theory]和[DataViaXxx]实现:

xunit.extensions.dll里附带了对数据驱动测试的支持,被称为Theory。用[Theory](代替[Test])来标记你的测试,再标记上其中一个[DataVia...]属性,用来指出数据的来源。

xUnit.net中的断言的数量也减少了。任何可用基本断言实现其功能的断言都被放弃。另外“is”和“are”(如“AreEqual”或“IsEmpty”)前缀也被去除。xUnit.net网站上提供了NUnit、MbUnit、MSTest与xUnit.net的属性和断言的详细对比

xUnit.net还用上了.NET 2.0和3.5的新语言特性。它支持使用泛型,因此可以在比较语句中保证类型安全,比如Equal和NotEqual断言。取代了[ExpectedException]属性的Assert.Throws()方法支持匿名委托和lambda表达式,因此代码更加紧凑也更具可读性:

Assert.Throws<InvalidOperationException> (delegate { operation(); }); // .NET 2.0
Assert.Throws<InvalidOperationException> (() => operation()); // .NET 3.5

测试类、测试方法和断言都很容易扩展。IComparer<T>接口让用户能够扩展Equal、NotEqual之类的功能。xUnit.net支持创建测试模式,测试模式控制着测试如何调用和执行。最后,用户还可以通过扩展现有的TestRunner或者自己新建TestRunner来控制测试套件和测试类的执行。

xUnit.net的创造者们显然认为他们这个开源框架会成为NUnit的接班人。而Roy Osherove觉得xUnit.net还不够成熟,未来还有些疑问。

查看英文原文:xUnit.net - Next Generation of Unit Testing Frameworks?

深度内容

模块化Java:声明式模块化

本文是模块化Java系列文章的第4篇,介绍的是声明式模块化。文中描述了组件如何以声明的方式来定义并组织在一起,而无需让代码依赖于OSGI API。

Ian Robinson和Jim Webber谈论基于Web的整合

本采访是在伦敦举行的QCon2009上记录的,Ian Robinson和Jim Webber探讨了如何将Web作为整合平台以及REST在理论上和实践中的好处。

项目管理修炼之道(精选版)

项目管理对于项目成败至关重要,但实践中每个项目都有自己的独特性,没有现成的解决方案可以套用。书中从应对实际风险的角度出发,讲述了从项目启动、项目规划到项目结束的整个管理流程,展示了作者的思考过程。本迷你书从原书中精选出5个章节。

那是鸟,还是飞机?不,那是超人!

在这个演讲中,Fred将会揭示敏捷的一些外在因素,并会重点关注敏捷获得成功的内在原因。从案例研究和真实的项目经验来看,Fred认为:工具、管理体系都不能让你变得敏捷。敏捷的成功,植根于士气高涨、充分授权的工作者身上,他们能够以不同以往的方式思考问题。

访谈和书摘:Eben Hewitt的新书《Java SOA Cookbook》

Java SOA Cookbook

Eben Hewitt的新书《Java SOA Cookbook》从Java实现的角度讨论了面向服务架构。Eben在书中讨论了SOA基础、工具、最佳实践和SOA治理等主题。

Mark Richard的《Java消息服务》第二版

Mark Richards的新书《Java消息服务》第二版覆盖了JMS的许多主题, 包括发布和订阅模式以及点对点模式,消息过滤和事务等。InfoQ与Mark谈论了跟他的新作。

模块化Java:动态模块化

本文是“模块化Java”系列文章的第三篇,讨论动态模块化,内容涉及如何解析bundle类、bundle如何变化、以及bundle之间如何通信。

让测试也敏捷起来

对于测试组织来说,敏捷方法带来的快速迭代却让测试本身变得困难起来:缺乏“足够详细的文档”,缺乏“仔细设计用例的时间”等等。在本演讲中,段念将与大家探讨如何在敏捷过程中进行测试。