【发布时间】:2009-08-17 16:47:12
【问题描述】:
我已经阅读了很多关于可用的 .NET 单元测试框架的信息。我不清楚的是区分可用框架的关键特性是什么。在评估单元测试框架时,您会寻找哪些必备功能?
【问题讨论】:
标签: .net unit-testing frameworks
我已经阅读了很多关于可用的 .NET 单元测试框架的信息。我不清楚的是区分可用框架的关键特性是什么。在评估单元测试框架时,您会寻找哪些必备功能?
【问题讨论】:
标签: .net unit-testing frameworks
这里有一些我正在寻找的东西
Assert.Throws 捕获的异常吗?断言是否能够以指定的容差进行数值比较?【讨论】:
我寻找的是工具集支持,我特别优先考虑的是持续集成支持。单元测试最重要的部分(至少对我来说,不是 TDD 的忠实粉丝)是将它们插入我的 CI 构建服务器。
出于这个原因,我偏爱 nUnit,因为 CruiseControl 中为它预先构建了构建任务,这是我选择的构建服务器。这并不是说您不能将任何其他测试框架插入 CC,nUnit 恰好是一个易于使用的框架。
至于可用功能,MSTest 有一些非常不错的附加组件,当您使用价格惊人的 Visual Studio Team System 以及后端的 TFS 运行它时。
说了这么多,各个测试框架的功能确实没有太大区别(我有使用 xUnit、nUnit 和 MSTest 的经验)——它们都允许您定义单元测试,并报告如何使用通过了,有多少失败了。它们都有某种 GUI,并且可以将它们全部与构建服务器集成。
【讨论】:
我同意它们在断言和其他基本功能方面都非常相似。它们开始不同的地方在于更高级的选项,例如脚本框架、构建工具、自动集成等。
如果您打算使用 CruiseControl.NET 之类的工具运行高度自动化的构建过程,并带有许多自定义构建选项和自定义脚本,我可能会使用 NUnit。根据测试结果,还有更多用于触发其他操作的钩子。
如果您刚刚开始进行单元测试并且只计划进行基本的集成测试,我会坚持使用 MStest,因为它与 Visual Studio 2008 紧密集成。(NUnit 有与 IDE 集成的选项,但更好的工具需要花钱.)
这是一个小比较表:
| NUnit | MStest
---------------------------------------------------------------------------------
Asserts | missing some collection asserts | missing some numeric/date asserts
---------------------------------------------------------------------------------
Speed | test run fast, faster setup on | w/ VS 2008 no setup necessary on
| servers and the like | the client, test run fairly fast.
---------------------------------------------------------------------------------
Options | a lot of 3rd party add-ons and | some 3rd party tools
| other tools |
---------------------------------------------------------------------------------
CC.NET | good integration, lots of tools | newer versions of CC.NET support
| and options | MS test out of the box, not as
| | many add on tools
---------------------------------------------------------------------------------
【讨论】:
他们都做同样的事情,如果他们不这样做,他们有扩展点,这意味着你可以完成同样的事情。从这个意义上说,您可以根据您在选择任何框架时使用的相同标准来评估它们(例如流行度 (NUnit)、MS-Certiffied (MS-Test) 等)
但是,如果您想获得有关选择的建议,我建议您阅读 XUnit "why did we build xunit" 页面,该页面指出了与单元测试框架相关的某些问题。
如果你想看到所有框架之间的一些相似之处,你可以从表中看到here,它们都有很多相似的特性,只是事物的不同说法。
当然,选择 BDD 框架是另一回事。
【讨论】:
我在几乎每个测试框架中错过的一件事是统一断言,我的意思是无论我断言什么,测试看起来都应该是一样的。我是否对值进行基于状态的断言,对模拟进行基于行为的断言,或者断言应该抛出异常。
我将使用 Ruby 作为示例,但这适用于任何环境。 (顺便说一句,您不仅限于使用 C# 框架来测试 .NET 应用程序,您可以使用任何 .NET 语言,当然 Ruby 就是其中之一,Python、Scheme、F# 等等也是如此。 )
这是 test/unit(JUnit 早期版本的一个端口),用于模拟 Mocha。
def test_state
assert_equal 2, 1+1
end
def test_exception
assert_raises(NoMethodError) { [].not_a_method }
end
def test_behavior
o = Object.new
o.expects(:ping).with(:pong)
o.ping(:pong)
end
注意所有的断言看起来是不同的,并且在不同的地方,实际的测试代码也在三个不同的地方。
这就是 Expectations,AFAIK 是唯一能做到这一点的框架。 (事实上,它是专门为统一断言而创建的。)不幸的是,由于作者不再从事任何 Ruby 工作,因此不再对其进行维护或支持。
expect 2 do
1+1
end
expect NoMethodError do
[].not_a_method
end
expect Object.new.to.receive(:ping).with(:pong) do |o|
o.ping(:pong)
end
注意断言看起来总是一样的,而且断言和测试代码总是在同一个位置。
不过,xUnit.Net 和 Mockito 等较新的框架肯定正在接近。
【讨论】:
面向开发人员的单元测试(请注意,我不是在谈论面向客户的验收测试!)就像生产代码:它们应该以一种显而易见的方式编写正在做。确实,这对于测试比对生产代码更重要,因为对于生产代码,您可以通过测试来告诉您代码是否有效,对于测试,您所拥有的只是阅读它们并查看它们是否有意义或不是。
因此,面向开发人员的单元测试不应该需要 cmets。并且测试名称是 cmets,因此,您的框架不应强迫您为测试命名。
这是一个例子(在RSpec中,当然也可以在.NET上使用,这次):
describe Array do
it 'should be empty' do
Array.new.should be_empty
end
end
这太愚蠢了。任何需要一个测试名称来理解这个测试在做什么的开发人员都应该认真地重新考虑他的职业选择。此外,所有与 cmets 相同的问题都适用:如果有人更改测试但忘记更改名称怎么办?现在这个名字不仅没用,而且还误导人!这好多了:
describe Array do
it do
Array.new.should be_empty
end
end
RSpec 还有一个妙招:它会自动为你测试的类创建一个实例,这样你就不必一遍又一遍地说ClassUnderTest.new.should,你可以说should :
describe Array do
it { should be_empty }
end
顺便说一句,就像开发人员可以弄清楚这是在测试什么一样,RSpec 也可以。如果您要求它提供客户可读的测试套件摘要,这就是它在所有三种情况下都会吐出的内容:
Array
- should be empty
【讨论】: