每个单元测试有多种安排/断言?
我们一群人(.NET 开发人员)正在谈论单元测试。不是任何一种框架(我们已经提到了 MSpec、NUint、MSTest、RhinoMocks、TypeMock 等)——我们只是泛泛而谈。
我们看到许多语法强制每个场景进行不同的单元测试,但我们没有看到一种方法可以将一个单元测试与各种输入或场景重复使用。此外,我们看不到在给定测试中实现多个断言的途径,而不会导致早期断言的失败威胁到后续断言的测试(在同一测试中)。
如今 .NET 单元测试(基于状态或行为)中是否发生了类似的情况?
A group of us (.NET developers) are talking unit testing. Not any one framework (we've hit on MSpec, NUint, MSTest, RhinoMocks, TypeMock, etc) -- we're just talking generally.
We see lots of syntax that forces a distinct unit test per scenario, but we don't see an avenue to re-using one unit test with various inputs or scenarios. Also, we don't see an avenue to multiple asserts in a given test without an early assert's failure threatening the testing of later asserts (in the same test).
Is there anything like that happening in .NET unit testing (state- or behavior-based) today?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
查看 NUnit 中的 [TestCase(params)]
允许使用不同的输入进行相同的测试。
另外,对于多重断言的事情,
看一下 OAPT(每个测试一个断言)运行程序 - 它承诺使用多个断言进行测试并将每个断言作为自己的测试运行:
http://rauchy.net/oapt/
look at [TestCase(params)] in NUnit
allows doing the same test with different inputs.
also, for the multiple asserts thing,
look at OAPT (One assert per test) runner - which promises to take a test with muliple asserts and run each assert as its own test:
http://rauchy.net/oapt/
“标准”设置/拆卸方法已经有助于重用测试代码。最重要的是,我相信许多 .Net 单元测试框架都实现了与 Java 对应的 JUnit 和 TestNG 相同或相似的功能,它们支持参数化测试等。
在我的解释中,测试方法测试单个用例。如果断言失败,则测试失败,并且有充分的理由尽快修复它。单元测试的正常状态应该是 100% 成功,在这种情况下,所有测试中的所有断言都通过。换句话说,失败的测试应该是例外而不是常态;而且我不太担心特殊情况。如果您仍然担心,您可以随时安排您的测试方法,使每个测试方法仅包含一个断言。
Already the "standard" setup / teardown methods help reusing test code a lot. On top of that, I believe many .Net unit test frameworks implement the same or similar features to their Java counterparts JUnit and TestNG, which support e.g. parametrized tests.
In my interpretation, a test method tests a single use case. If there is an assertion failure, that test fails, and there is a good reason to fix it asap. The normal state of unit tests should be 100% success, in which case all assertions in all tests pass. In other words, a failing test should be the exception rather than the norm; and I tend not to worry about exceptional cases too much. If it still worries you, you can always arrange your test methods to contain only a single assertion each.
使用 MBUnit 中的 RowTest 或 xUnit.net 中的 Theories 来改变输入变量是很常见的。谷歌其中之一,你会发现几个例子。 Ben Hall 有一篇关于在 xUnit.net 中使用理论的精彩文章: http://blog.benhall.me.uk/2008/01/introduction-to-xunitnet-extensions.html
在单个测试中使用多个断言是很好的(而且很常见)。这里需要遵循的概念是单个单元测试应该测试特定行为或单个代码单元。如果一个单元测试中有 3 个断言,并且第一个断言失败,则此时其他 2 个断言是否通过并不重要(并且大多数测试运行者在一个测试失败后不会在单个测试中运行其余断言) ,重要的是一个失败的断言。
关于每次测试是否应该测试多个行为/代码单元,有很多意见。出于多种原因,我更喜欢每次测试一种行为。最重要的是,当其中一项测试失败时,我或其他人将不得不返回并阅读测试,以准确了解失败的原因和原因。如果我们必须通读一个不仅仅测试单个行为的单元测试,那么我们就是在浪费时间。在较小的块中进行测试时,确保为代码编写正确的测试也更容易。我强烈建议您阅读 Roy Osherove 的《单元测试的艺术》单元测试的艺术。
Varying input variables is quite common using RowTest in MBUnit or Theories in xUnit.net. Google either one of those and you'll find several examples. Ben Hall has a great post about using Theory in xUnit.net: http://blog.benhall.me.uk/2008/01/introduction-to-xunitnet-extensions.html
Having multiple asserts in a single test is fine (and common). The concept that needs to be followed here is that a single unit test should be testing a specific behavior or single unit of code. If you have 3 asserts in one unit test, and the first one fails, whether the other 2 pass or not at this point is not important (and most test runners will not run the rest of the asserts in a single test after one fails), what is important is the one failing assert.
There are a lot of opinions out there on whether or not there should be more than one behavior / unit of code tested per test. I prefer one behavior per test for many reasons. The most important one being that when one of those tests fails, I or someone else will have to go back and read the test to see exactly what is failing and why. If we have to read through a unit test that is doing more than just testing a single behavior, then we're wasting time. It's also much easier to make sure that you're writing the correct tests for your code when testing in smaller chunks. I highly recommend getting a copy of Roy Osherove's The Art of Unit Testing.
您可以采取的一种解决方案是将场景放入 SetUp 函数中。
在 NUnit 中,您可以使用如下方法:
private class1 c1;
然后进行两个测试:
每次执行测试之前都会调用 SetUp。我想您可以使用构造函数执行类似的操作,该构造函数将被调用一次。
也就是说,有一些很好的论据反对这一点,因为单独的测试应该设置它需要的一切。但这些并不是硬性规定。
One solution you could do, is to put the scenario in a SetUp function.
In NUnit you could have a method like:
private class1 c1;
Then have two tests:
The SetUp gets called each time before a test is executed. I suppose you could do something similar with a constructor that would get called once.
That said, there are some good arguments against that, in that an individual test should set up everything it needs. But those aren't hard-and-fast rules.