如何在BDD中进行模拟测试?

23

我知道Dan North在设计BDD时的一个意图是将词汇从测试领域的复杂性中抽离出来。然而,在实施外部驱动模式时,似乎我们仍需要一些对模拟行为(或者如果您愿意,存根行为)的理解。North在这个视频中建议,如果我从最外层的领域对象开始并向内部工作,我会在发现协作者时模拟协作者,然后稍后用正确的实现替换它们。因此,最终我会得到一组端到端测试。

Martin Fowler在这篇博客文章中似乎看到了不同的东西,他将TDD分为两派:“传统TDD”尽可能使用真实对象,在必要时使用模拟;而“模拟TDD”则更喜欢在大多数情况下使用模拟。他认为BDD倾向于后者。也就是说,在开发功能的最后,采用“模拟派”方法将保留实际测试中的模拟内容(很抱歉在BDD讨论中使用这个词)。

公平地说,两个资料都已经过时了,也许随着BDD在单元级别和验收级别之间的应用逐渐明晰,情况会变得更清楚。

但我的问题是:当我的需求完成时,我的场景实际上应该有多少端到端测试? North解释说,BDD需要抽象。例如,当我测试登录行为时,我的场景将详细说明登录过程的含义。然而,在进行其他需要但不涉及登录的场景时,我不想一遍又一遍地执行这些步骤。我希望有一个简单的抽象,仅仅说“假设我已经登录”,这样我就可以执行其他行为。

看起来我的抽象方法将是模拟某些协作者(或提供“测试替身”),而有些情况可能会比其他情况更多地使用它们。例如,我是否总是要模拟外部资源,如数据库或邮件服务器?

也许我问错了问题。BDD关注的是沟通、缩短反馈周期以及发现你不知道的东西。也许选择模拟什么和不模拟什么是无关紧要的问题,只要我们感兴趣的行为实际上是有效的。我很想知道别人在这方面的做法。

3个回答

8
对我来说,BDD允许我验证我是否构建了正确的东西。这意味着如果我将我的应用程序插入到实际数据库中并使用真实的UI,则它应该正确运行。这就是你所谓的端到端。
现在,如果我将我的应用程序插入到内存存储中,并通过其API级别与应用程序进行交互(仅在UI下方),那么我会期望它以完全相同的方式运行。
现在问题来了,我们需要明确我们在BDD中所指的行为,我们在做BDD时感兴趣的是什么行为。
在我的情况下,如果我从用户故事开始编写场景,我主要感兴趣的是通过我的应用程序API、服务层、域实体、助手等传递的行为……主要是我不太关心UI或数据库中会发生什么。真正重要的是在服务器端编写的所有代码。这就是我感兴趣的行为。如果您像这样考虑,摆脱UI和DB就是有意义的,因为我们不关心这些东西。 UI的期望行为是显示我的应用程序给出的数据。UI是一个愚蠢的东西。 DB的期望行为是存储和检索我的应用程序提供或需求的实体。这也是一个非常愚蠢的事情。现在,所有其他的东西都是智能的,我对此负责。
因此,我很乐意在没有UI和使用内存版本的存储库的情况下运行我的BDD场景。从中获得的好处是非常快速、专注和可维护的测试。
关于UI和DB,我会编写JavaScript单元测试来测试其中的行为。今天,一些UI可能具有大量显示逻辑来隐藏和显示内容,但这种行为与我的用户故事BDD场景中的行为不同(它们不应该涉及UI)。
对于DB,我会编写集成测试,仅检查我的真实存储库是否能够在DB上读取和写入内容。
最后,我将编写一些端到端测试,以确保一切连接在一起时都正常。

7

我认为关键是专注于BDD中的B——行为。

目前,我倾向于忽略UI元素并模拟持久层——毕竟,这些层中很少有任何业务逻辑(我们倾向于使用预先存在且经过充分测试的框架直接将对象模型绑定到UI或DB)。

以最近构建的一个简单WPF应用程序为例:验收测试使用ViewModel作为应用程序的入口/外部点,从数据存储库开始的所有内容都被模拟了。 应用程序的所有规则和逻辑都存在于两者之间——而实际上,这些是需要指定和测试的应用程序行为。


1

需要模拟什么取决于架构。对于MVVM,您可以模拟模型以测试视图模型。对于MVP,您可以模拟视图和/或模型以测试演示文稿。如果您想编写端到端测试而不是单元测试,那么您可以通过视图模型/演示文稿测试应用程序的另一端(服务/数据库层)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接