我的每个单元测试应该检查多少?例如,我有这个测试
[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>));
}
显然,如果第一次测试失败,那么第二次测试是否会失败,那么这两次测试是否应合并为一次测试?我的感觉是,测试越精细,每个测试检查越少,找到失败原因的速度就越快。但是,进行大量非常小的测试会产生开销,这可能会花费时间来运行所有测试。
答案 0 :(得分:12)
我建议尽可能地将它们分解。
有很多原因,恕我直言最重要的是:
当您的某个测试失败时,您希望能够尽可能快速,安全地隔离出错的地方。让每个测试方法只测试一件事是实现这一目标的最佳方法。
每个测试都需要从一个干净的平板开始。如果您创建一次存储库然后在2个或更多测试中使用它,那么您对这些测试的顺序具有隐式依赖性。假设Test1将一个项添加到存储库但忘记删除它。 Test2的行为现在会有所不同,并可能导致您的测试失败。唯一的例外是不可变数据。
关于速度问题,我不担心。对于像这样的纯代码运算,.NET 非常快,你永远无法分辨出来。一旦你完成代码处理和数据库之类的事情,你就会感觉到性能问题,但是一旦你这样做,就会遇到如上所述的所有“干净的问题”,所以你可能只是必须忍受它(或尽可能多地使你的数据不变)。
祝你的测试好运。
答案 1 :(得分:3)
越细,越好。当断言在测试用例中失败时,测试用例不再运行。案件的后半部分可能会发现其他错误。
如果测试用例之间存在共享代码,请使用setup / teardown函数来处理这些问题,而不会过多地重复自己。时间成本通常可以忽略不计。如果设置/拆卸花费太多时间,您可能不会进行单元测试,而是进行一些更高级别的自动化测试。理想情况下,单元测试不应具有文件系统,网络,数据库等依赖性。
答案 2 :(得分:2)
我认为“标准”的答案是它应该达到这样的程度:如果代码中存在错误,它应该打破一个测试,但不能隐藏任何其他错误(不会阻止其他测试运行)这个失败了。每个测试测试一件事,两个测试不测试相同的东西。这是理想的,并不总是可以实现的。称之为指导。
话虽如此,它确实是一门艺术。我最初会抛开性能问题,更多地关注可维护性。那里有两条半到三条重复线。如果设计发生变化,那将很难维护。在这种情况下,复制本身可以通过设置方法和类中的字段来解决,但主要担心的是可维护性。
测试应该足够小,以便可维护,易于理解,以及使其他人(或者你经过一段时间后)理解代码正在做什么并能够维持测试的合理性。
答案 3 :(得分:0)
单元测试应该从功能设计的角度准确测试技术设计中描述的内容。
答案 4 :(得分:0)
测试测试的方法肯定是您需要事先决定并坚持下去的方法。我不相信每个人都应该统一地遵循相同的方法,因为不同的团队和/或项目在编码,性能,故障排除,测试基础设施等方面具有不同的优先级。但是保持一致将始终有所帮助:
如果您认为性能更重要,那么使用更多验证/断言来实现更厚的测试。如果您认为故障排除是最重要的,那么请根据需要隔离您的测试。我不明白为什么厚实和结构良好的测试存在缺陷。这样的测试可以完成与更大量的更薄测试相同的工作。
当然,每个测试仍然需要关注特定的功能/特性,但这不是这个主题的主题。