22

我知道 Dan​​ North 设计 BDD 的意图之一是让词汇表远离测试领域的复杂性。但是,在实现由外向内的方法时,我们似乎仍然需要对模拟行为(或存根行为,如果您愿意的话)有所了解。North 在此视频中建议,如果我从最外层的域对象开始,然后向内工作,我会在发现协作者时模拟它们,然后用适当的实现替换它们。所以最后,我得到了一组端到端的测试。

Martin Fowler 在这篇博文中定义了 TDD 的两个阵营时似乎对此有所不同:“经典 TDD”尽可能使用真实对象,必要时使用模拟,以及“模拟 TDD”,在大多数情况下更喜欢模拟。他认为 BDD 倾向于后者。即,在开发功能结束时,“mockist”方法会在实际测试中留下模拟(抱歉在 BDD 讨论中使用该词)。

公平地说,这两种材料都有多年的历史了,也许随着 BDD 在单元级别应用和接受级别之间的界限发展,事情变得更加清晰。

但我对社区的问题基本上是:当我的故事完成后,我的场景实际上应该进行多少端到端测试? North解释说 BDD 需要抽象。例如,当我测试登录行为时,我的场景将详细说明登录过程的含义。但是,当我在做其他一些需要但不是关于登录的场景时,我不想一遍又一遍地执行这些步骤。我想要一个简单的抽象,简单地说“假设我已登录”,这样我就可以执行我的其他行为。

因此,我的抽象方法似乎是模拟某些合作者(或提供“测试替身”),并且某些场景可能比其他场景更多地使用它们。例如,我是否总是模拟外部资源,例如数据库或邮件服务器?

也许我问错了问题。BDD 就是关于沟通、缩短反馈周期和发现你不知道的东西。只要我们感兴趣的行为确实有效,也许什么和什么不嘲笑是一个无关紧要的问题。我很好奇其他人的方法是什么。

4

3 回答 3

8

对我来说,BDD 允许我验证我是否构建了正确的东西。这意味着如果我将我的应用程序插入一个真实的数据库并使用真实的 UI,它应该可以正常运行。这就是你所说的端到端。

现在,如果我将我的应用程序插入到内存存储中,并通过其 API 级别(就在 UI 下方)与应用程序对话。我希望它的行为方式完全相同。

事情就是这样,我们需要清楚我们所说的行为是什么意思,当我们做 BDD 时,我们感兴趣的行为是什么。

就我而言,如果我从用户故事开始并编写场景,我主要对通过我的应用程序 API、服务层、域实体、帮助程序等的行为感兴趣……主要是我不太感兴趣在 UI 或数据库中会发生什么。真正的肉是在服务器端编写的所有代码。这就是我感兴趣的行为。如果你这样认为,摆脱 UI 和 DB 是有意义的,因为我们不关心这些人。UI 的预期行为是显示我的应用程序提供的数据。用户界面是一个愚蠢的东西。数据库的预期行为是存储和检索我的应用程序提供或想要的实体。这也是一件非常愚蠢的事情。现在其他一切,这就是所有的聪明之处,我负责。

所以我很乐意在没有 UI 的情况下运行我的 BDD 场景,并使用我的存储库的内存版本。我从中获得的好处是非常快速、专注和可维护的测试。

关于 UI 和 DB,我会编写 javascript 单元测试来测试那里的行为,今天一些 UI 可以有很多显示逻辑来隐藏和显示东西,但这种行为与我的用户故事 bdd 中的行为不同场景(他们不应该谈论 UI)。

对于数据库,我编写集成测试只是为了检查我的真实存储库是否能够在数据库上读取和写入内容。

最后我只写了几个端到端的测试来检查连接在一起时一切是否正常。

于 2012-10-05T21:24:25.353 回答
7

我认为关键是关注 BDD 的 B - 行为。

目前我倾向于忽略 UI 元素并模拟掉持久层——毕竟这些天在这些层中几乎没有业务逻辑(我们倾向于使用预先存在的和直接将对象模型绑定到 UI 或 DB)经过大量测试的框架)。

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

于 2012-05-25T15:22:04.117 回答
1

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

于 2012-05-25T17:15:15.527 回答