我已经阅读了很多关于可用的.NET单元测试框架的资料。对我来说不清楚的是,这些可用框架之间有哪些关键特性区别。在评估单元测试框架时,您寻找的必备功能是什么?
我已经阅读了很多关于可用的.NET单元测试框架的资料。对我来说不清楚的是,这些可用框架之间有哪些关键特性区别。在评估单元测试框架时,您寻找的必备功能是什么?
Assert.Throws
捕获异常吗?这些断言能否进行带指定公差的数值比较?我同意在断言和其他基本功能方面它们都非常相似。它们开始有所不同的地方在于更高级的选项,例如脚本框架、构建工具、自动化集成等。
如果您打算使用像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
---------------------------------------------------------------------------------
在几乎所有测试框架中我都感到缺失的一件事是统一的断言,我的意思是无论我断言什么,测试应该看起来都一样。无论是对值进行基于状态的断言、对模拟对象进行基于行为的断言,还是断言应该抛出异常。
我将以Ruby为例,但这适用于任何环境。(另外,你不必局限于使用C#框架测试.NET应用程序,你可以使用任何.NET语言,其中当然包括Ruby,Python,Scheme,F#等)
这是使用Mocha进行模拟的test/unit
(JUnit早期版本的移植)。
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
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
面向开发人员的单元测试(请注意,我不是在谈论面向客户的验收测试!)就像生产代码一样:它们应该以明显的方式编写,以便清楚地了解它们正在做什么。实际上,这对于测试比生产代码更重要,因为对于生产代码,您有测试来告诉您代码是否有效,而对于测试,您只能阅读它们并查看它们是否有意义。
因此,面向开发人员的单元测试不应需要注释。而测试名称就是注释,因此,您的框架不应强制您命名测试。
以下是一个示例(在RSpec中,当然也可以在.NET上使用):
describe Array do
it 'should be empty' do
Array.new.should be_empty
end
end
这太愚蠢了。任何需要测试名称才能理解此测试正在做什么的开发人员都应认真重新考虑自己的职业选择。此外,所有与注释相关的问题也同样适用:如果有人更改了测试但忘记更改名称怎么办?现在名称不仅无用,而且具有误导性!这个更好:
describe Array do
it do
Array.new.should be_empty
end
end
describe Array do
it { should be_empty }
end
Array
- should be empty
它们都做着同样的事情,如果不是这样,它们就有扩展点,这意味着你可以完成同样的事情。在这个意义上,你可以根据选择任何框架时使用的相同标准来评估它们(例如:流行度(NUnit),MS-Certiffied(MS-Test)等等)。
然而,如果你想要选择一个建议,我建议你阅读XUnit "why did we build xunit"页面,该页面指出了关于单元测试框架的某些问题。
如果你想看到所有框架之间的一些相似之处,你可以从here表格中看到,它们都有很多相似的特性,只是用不同的词来描述。
当然,选择BDD框架是另一回事。