每个单元测试应该测试多少?
我的每个单元测试应该检查多少内容? 例如,我有这个测试
[TestMethod]
public void IndexReturnsAView()
{
IActivityRepository repository = GetPopulatedRepository();
ActivityController activityController = GetActivityController(repository);
ActionResult result = activityController.Index();
Assert.IsInstanceOfType(result, typeof(ViewResult));
}
,显然
[TestMethod]
public void IndexReturnsAViewWithAListOfActivitiesInModelData()
{
IActivityRepository repository = GetPopulatedRepository();
ActivityController activityController = GetActivityController(repository);
ViewResult result = activityController.Index() as ViewResult;
Assert.IsInstanceOfType(result.ViewData.Model, typeof(List<Activity>));
}
如果第一个测试失败,那么第二个测试也会失败,那么这两个测试是否应该组合成一个带有两个断言的测试? 我的感觉是,测试越细粒度,每次测试检查越少,找到失败原因的速度就越快。 然而,进行大量非常小的测试会产生开销,这可能会花费时间来运行所有测试。
How much should each of my unit tests examine? For instance I have this test
[TestMethod]
public void IndexReturnsAView()
{
IActivityRepository repository = GetPopulatedRepository();
ActivityController activityController = GetActivityController(repository);
ActionResult result = activityController.Index();
Assert.IsInstanceOfType(result, typeof(ViewResult));
}
and also
[TestMethod]
public void IndexReturnsAViewWithAListOfActivitiesInModelData()
{
IActivityRepository repository = GetPopulatedRepository();
ActivityController activityController = GetActivityController(repository);
ViewResult result = activityController.Index() as ViewResult;
Assert.IsInstanceOfType(result.ViewData.Model, typeof(List<Activity>));
}
Obviously if the first test fails then so will the second test so should these two be combined into one test with two asserts? My feeling is that the more granular the tests and the less each test checks the faster it will be to find the causes of failures. However there is overhead to having a huge number of very small tests which might cost time in running all the tests.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我建议尽可能地分解它们。
造成这种情况的原因有很多,恕我直言,最重要的原因是:
当您的其中一个测试失败时,您希望能够尽可能快速、安全地准确找出问题所在。 让每个测试方法只测试一件事情是实现这一目标的最佳方法。
每个测试都需要从头开始。 如果您创建存储库一次,然后在 2 个或更多测试中使用它,那么您对这些测试的顺序有隐式依赖。 假设 Test1 将一个项目添加到存储库但忘记删除它。 Test2 的行为现在将有所不同,并可能导致您的测试失败。 唯一的例外是不可变数据。
至于你的速度问题,我不会担心。 对于像这样的纯粹代码处理,.NET非常快,而且您永远无法区分其中的差异。 一旦你摆脱代码处理并进入数据库之类的事情,那么你就会感受到性能问题,但是一旦你这样做,你就会遇到如上所述的所有“干净的石板”问题,所以你可能只是必须忍受它(或者使尽可能多的数据不可变)。
祝您测试顺利。
I'd recommend breaking them down as much as possible.
There are lots of reasons for this, IMHO the most important ones are:
When one of your tests fails, you want to be able to isolate exactly what went wrong as quickly and as safely as possible. Having each test-method only test one single thing is the best way to achieve this.
Each test needs to start with a clean slate. If you create the repository once and then use it in 2 or more tests, then you have an implicit dependency on the order of those tests. Say Test1 adds an item to the repository but forgets to delete it. Test2's behavior will now be different, and possibly cause your test to fail. The only exception to this is immutable data.
Regarding your speed concerns, I wouldn't worry about it. For pure code-crunching like this, .NET is very fast, and you'll never be able to tell the difference. As soon as you get out of code-crunching and into things like databases, then you'll feel the performance issues, but as soon as you do that you run into all the "clean slate" issues as described above, so you may just have to live with it (or make as much of your data immutable as possible).
Best of luck with your testing.
粒度越细越好。 当测试用例中的断言失败时,该测试用例将不再运行。 该案的后半部分可能会发现其他错误。
如果测试用例之间存在共享代码,请使用设置/拆卸函数来处理该问题,而无需过多重复。 时间成本通常可以忽略不计。 如果设置/拆卸花费太多时间,您可能没有进行单元测试,而是进行了一些更高级别的自动化测试。 理想情况下,单元测试不应具有文件系统、网络、数据库等依赖项。
The more fine-grained the better. When an assert fails in a test case, the test case is not run any further. The latter parts of the case could potentially uncover other errors.
If there's shared code between test cases, use setup/teardown functions to take care of that without repeating yourself too much. Time cost is often negligible. If the setup/teardown takes too much time, you're probably not doing unit testing but some higher level automated testing. Unit tests ideally should not have file system, network, database etc. dependencies.
我认为“标准”答案是,如果代码中存在错误,它应该破坏一个测试,但当此测试失败时,不会隐藏任何其他失败(不会阻止其他测试运行) 。 每个测试测试一件事,两次测试不会测试同一件事。 这是一个理想,并不总是可以实现的。 称之为指导。
话虽如此,这确实是一门艺术。 我一开始会先把性能问题放在一边,更多地关注可维护性。 那里有两行半到三行重复。 如果设计发生变化,维护就会变得困难。 在这种情况下,重复本身可以通过类中的设置方法和归档来解决,但主要担心的是可维护性。
测试应该足够小,以便可维护、易于理解,并且可以让其他人(或一段时间后的您)合理地理解代码在做什么并能够维护测试。
I think the "standard" answer is that it should get to the point that if there is a bug in the code, it should break one test, but not hide any other failures (not stop the other tests from running) when this one fails. Each test tests one thing and two tests don't test the same thing. That's an ideal, not always acheivable. Call it guidance.
That being said, it is really an art. I would put aside performance issues initially, and focus more on maintainability. There you have two and a half to three lines of duplication. If the design changes, that will get hard to maintain. The duplication per se can be solved by a setup method an a filed in the class in this case, but the main thing to worry about is maintainability.
The tests should be small enough to be maintainable, easy to understand, and something that makes it reasonable for others (or you after time has passed) to understand what the code is doing and be able to maintain the tests.
单元测试应该从功能设计的角度准确测试技术设计中描述的内容。
A unit test should exactly test that what is described in your technical design in perspective of the functional design.
关于测试测试多少的方法绝对是您需要预先决定并坚持下去的事情。 我不认为每个人都应该统一遵循相同的方法,因为不同的团队和/或项目在编码、性能、故障排除、测试基础设施等方面有不同的优先级。但保持一致总是有帮助的:
您事先知道要挖多深;
你的测试;
测试助手类的同时
实施测试。
如果您认为性能更重要,那么可以通过更多验证/断言来实施更厚的测试。 如果您认为故障排除至关重要,那么请根据需要隔离您的测试。 我不明白为什么厚重且结构良好的测试有缺陷。 这样的测试可以完成与更多的稀释剂测试相同的工作,而且效果也一样。
当然,每个测试仍然需要关注特定的功能/特性,但这不是本线程的真正主题。
The approach on how much a test tests is definitely something that you need to decide up front and stick to it. I don't believe that everyone should follow the same approach uniformly, since different teams and/or projects have different priorities towards coding, performance, troubleshooting, test infrastructure, etc. But being consistent will always help:
you know in advance how deep to dig;
your tests;
of test helper classes while
implementing tests.
If you decide that performance is more important then implement thicker tests with more validations/asserttions. If you decide that troubleshooting is a paramount then isolate your tests as much as needed. I can't see why thick and well structured tests are flawed. Such tests would get the same job done as greater amount of thinner tests and just as well.
Of course, every test still needs to focus on particular function/feature but this is not really topic of this thread.