13

我知道优势是什么,并且在处理更复杂的系统时会使用假数据。

如果我正在开发一些简单的东西,我可以很容易地在一个真实的数据库中设置我的环境,并且正在访问的数据非常小,以至于访问时间不是一个因素,我只运行了几个测试。

创建假数据仍然很重要,还是我可以忘记额外的编码并直接跳到真实数据?

当我说真实数据库时,我指的不是生产数据库,而是测试数据库,而是使用真实的实时 DBMS 和与真实数据库相同的模式。

4

11 回答 11

20

使用假数据而不是真实数据库的原因是:

  1. 速度。如果您的测试很慢,您将不会运行它们。模拟数据库可以使您的测试运行得比其他方式快得多。
  2. 控制。您的测试需要成为测试数据的唯一来源。当您使用假数据时,您的测试会选择您将使用哪些假数据。因此,您的测试不可能因为有人以不熟悉的状态离开数据库而被破坏。
  3. 秩序独立。我们希望我们的测试能够以任何顺序运行。一个测试的输入不应依赖于另一个测试的输出。当您的测试控制测试数据时,测试可以彼此独立。
  4. 环境独立。您的测试应该可以在任何环境中运行。您应该能够在火车上、飞机上、家中或工作中运行它们。他们不应该依赖外部服务。当您使用假数据时,您不需要外部数据库。

现在,如果您正在构建一个小型应用程序,并且通过使用真正的数据库(如 MySQL)可以实现上述目标,那么请务必使用数据库。我愿意。但是不要误会,随着应用程序的增长,您最终将面临模拟数据库的需要。没关系,当你需要的时候做。雅尼。只要确保你在需要时这样做。如果你放手,你会付出代价的。

于 2009-03-05T20:46:37.877 回答
2

这有点取决于你想测试什么。通常您想测试代码中的实际逻辑而不是数据库中的数据,因此设置一个完整的数据库只是为了运行您的测试是浪费时间。

还要考虑维护测试和测试数据库的工作量。使用数据库测试您的代码通常意味着您正在测试整个应用程序,而不是孤立地测试不同的部分。这通常会导致大量工作使数据库和测试保持同步。

最后一个问题是测试应该独立运行,因此每个测试应该在自己的数据库版本上运行,或者让它保持与测试运行前完全相同的状态。这包括测试失败后的状态。

话虽如此,如果你真的想在你的数据库上进行测试,你可以。有一些工具可以帮助设置和拆除数据库,例如dbunit

我见过有人尝试像这样创建单元测试,但结果几乎总是比实际价值要多得多。大多数在项目中途放弃它,大多数在项目期间完全放弃 ttd,一般认为经验转移到单元测试。

因此,我建议保持测试简单和隔离,并将您的代码封装得足够好,以便可以单独测试您的代码。

于 2009-03-03T19:09:37.423 回答
2

至于 Real DB 不会妨碍您,并且您可以通过这种方式更快地进行操作,我会务实并坚持下去。

在单元测试中,“测试”比“单元”更重要。

于 2009-03-03T19:25:18.370 回答
2

我认为这取决于您的查询是否在存储库中固定(更好的选择,IMO),或者存储库是否公开可组合查询;例如 - 如果您有一个存储库方法:

IQueryable<Customer> GetCustomers() {...}

然后你的 UI 可以请求:

var foo = GetCustomers().Where(x=>SomeUnmappedFunction(x));

bool SomeUnmappedFunction(Customer customer) {
   return customer.RegionId == 12345 && customer.Name.StartsWith("foo");
}

这将通过基于对象的虚假 repo,但对于实际的db 实现将失败。当然,您可以通过让存储库在内部处理所有查询(无外部组合)来取消这一点;例如:

Customer[] GetCustomers(int? regionId, string nameStartsWith, ...) {...}

因为这个不能组合,所以可以单独检查DB和UI。使用可组合查询,如果您希望它有用,就必须自始至终使用集成测试。

于 2009-03-03T19:38:57.603 回答
1

这取决于数据库是否由测试自动设置,也取决于数据库是否与其他开发人员隔离。

目前它可能不是问题(例如只有一个开发人员)。但是(对于手动数据库设置)设置数据库是运行测试的额外障碍,这是一件非常糟糕的事情。

于 2009-03-03T18:57:58.967 回答
1

如果您只是在编写一个您绝对知道不会增长的简单一次性应用程序,我认为很多“最佳实践”都被抛在了脑后。

如果您编写的只是一个简单的“联系我们”表单,则无需使用DI/IOC 或进行单元测试或模拟您的数据库访问。但是,很难在“简单”应用和“复杂”应用之间划清界限。

换句话说,请使用您的最佳判断,因为对此没有一成不变的答案。

于 2009-03-03T18:59:10.430 回答
1

假设您想自动执行此操作,最重要的是您可以以编程方式生成初始条件。听起来就是这样,甚至更好的是您正在测试真实世界的数据。

但是,有一些缺点:

您的真实数据库可能无法涵盖代码中的某些条件。如果你有虚假数据,就会导致这种行为发生。

正如您所指出的,您有一个简单的应用程序;当它变得不那么简单时,您将希望拥有可以归类为单元测试和系统测试的测试。单元测试应该针对一个简单的功能,这将更容易处理假数据。

于 2009-03-03T18:59:45.247 回答
1

只要您不将它们视为“单元”测试,就可以针对该场景执行此操作。那些将是集成测试。您还需要考虑是否会一次又一次地通过 UI 进行手动测试,因为您可能只是自动化了冒烟测试。鉴于此,您甚至可以考虑根本不进行集成测试,而只在功能/用户界面测试级别工作(因为它们已经涵盖了集成)。

正如其他人所指出的那样,很难在复杂/非复杂上划清界限,而且你现在通常会为时已晚:(。如果你已经习惯这样做,我相信你不会得到太多开销。如果不是这样,你可以从中学习:)

于 2009-03-03T19:19:44.403 回答
0

这是一个非常简单的应用程序,您看不到它在增长,我认为在真实数据库上运行您的测试没有问题。但是,如果您认为此应用程序会增长,那么在测试中说明这一点很重要。

让一切尽可能简单,如果您以后需要更灵活的测试,那就这样做吧。不过要提前计划,因为您不希望在 3 年内拥有一个依赖于旧的和 hacky(对于大型应用程序)测试的大型应用程序。

于 2009-03-03T18:55:07.520 回答
0

假存储库的一个优点是您的回归/单元测试是一致的,因为您可以预期相同查询的相同结果。这使得构建某些单元测试变得更加容易。

如果您的代码(如果不是只读查询)修改数据,则有几个缺点: - 如果您的代码中有错误(这可能是您测试的原因),您最终可能会破坏生产数据库。即使你没有打破它。- 如果生产数据库随着时间的推移发生变化,尤其是在您的代码执行时,您可能会忘记添加的测试材料,并且以后很难将其从数据库中清除。- 来自访问数据库的其他系统的生产查询可能会将您的测试数据视为真实数据,这可能会破坏未来某处重要业务流程的结果。例如,即使您用某个标志或前缀标记了您的数据,您能否保证访问数据库的任何人都将遵守此模式?

此外,某些数据库受隐私法监管,因此根据您的合同和谁拥有主数据库,您可能会或可能不会被法律允许访问真实数据。

如果您需要在生产数据库上运行,我建议您在可以在高峰时段轻松创建的副本上运行。

于 2009-03-03T18:57:39.433 回答
0

对数据库运行测试的缺点是速度慢,并且在运行测试之前设置数据库状态很复杂。

如果您对此有控制权,那么直接针对数据库运行测试就没有问题;这实际上是一种很好的方法,因为它比针对虚假数据运行更好地模拟您的最终产品。关键是采取务实的方法,将最佳实践视为指导方针而不是规则。

于 2009-03-03T19:00:46.057 回答