我知道Dan North设计BDD的意图之一是将词汇从测试域的复杂性中移开。但是,在实现从外到内的方法时,似乎我们仍然需要对模拟行为(或者如果您愿意,还是存根行为)有所了解。 North在this video中建议,如果我从最外层的域对象开始并向内工作,我会在发现它们时模拟协作者,然后用适当的实现替换它们。所以最后,我最终得到了一系列端到端测试。
当他定义两个TDD阵营时,马丁福勒似乎在this blog post看到了一点点不同:“经典TDD”尽可能使用真实物体,必要时使用模拟物,而“模仿者TDD”更喜欢嘲笑在大多数情况下。他看到BDD倾向于后者。即,在开发特征结束时,“模仿者”方法会在实际测试中留下嘲笑(很遗憾在BDD讨论中使用该词)。公平地说,这两种材料都已经存在多年了,随着BDD在单元级应用和接受级别之间的界限发展,事情也变得更加清晰。
但我对社区的问题基本上是:当我的故事完成后,我的方案实际上应该进行多少端到端测试? BDD要求的北方explains抽象。例如,当我测试登录行为时,我的方案将详细说明登录过程的含义。但是,当我正在做需要但不是登录的其他场景时,我不想一遍又一遍地执行这些步骤。我想要一个简单的抽象,简单地说“鉴于我已登录”,所以我可以执行其他行为。
所以我的抽象方法似乎是模仿某些协作者(或者提供“测试双重”),而某些场景可能比其他场景更多地使用它们。例如,我是否总是模拟外部资源,例如数据库或邮件服务器?
也许我问的是错误的问题。 BDD就是沟通,缩短反馈周期,发现你不知道的东西。即使我们感兴趣的行为确实有效,也许什么也不是模拟是一个无关紧要的问题。我很好奇其他人的做法是什么。
答案 0 :(得分:7)
我认为关键是关注BDD的行为 - 行为。
目前我倾向于忽略UI元素并模拟持久层 - 在这些日子之后,这些层中几乎没有任何业务逻辑(我们倾向于使用pre将对象模型直接绑定到UI或DB - 存在且经过严格测试的框架)。
作为示例,在我正在构建的最近(简单)WPF应用程序中:验收测试使用ViewModel作为应用程序的入口/外部点 - 并且数据存储库中的所有内容都被模拟。应用程序的所有规则和逻辑都存在于两者之间 - 实际上,这些是应用程序需要指定和测试的行为。
答案 1 :(得分:7)
对我来说BDD允许我验证我已经建立了正确的东西。 这意味着如果我将我的应用程序插入真实数据库并使用真实UI,它应该正常运行。那是你正在谈论的端到端。
现在,如果我将应用程序插入内存存储器中,并通过其API级别与应用程序通信(那么就在UI下方)。我希望它的行为方式完全一样。
现在就是这样,我们需要清楚我们的行为是什么意思,当我们做BDD时,我们感兴趣的行为是什么。
就我而言,如果我从用户故事开始并编写场景,我主要对通过我的应用程序API,服务层,域实体,帮助程序等的行为感兴趣...主要是我不是对UI和数据库中会发生什么感兴趣。真正的肉是服务器端编写的所有代码。这就是我感兴趣的行为。如果你认为这样摆脱UI和数据库是有道理的,因为我们不关心这些人。 UI的预期行为是显示我的应用程序提供的数据。用户界面是一个愚蠢的事情。 DB的预期行为是存储和检索应用程序提供或想要的实体。这也是一件非常愚蠢的事情。现在其他一切,那就是所有的聪明才智,我负责。
因此,我很乐意在没有UI并使用内存版本的存储库的情况下运行我的BDD场景。我得到的奖励实际上是非常快速,专注和可维护的测试。
关于UI和数据库,我会编写javascript单元测试来测试那里的行为,今天一些UI可以有很多显示逻辑来隐藏和显示东西,但这种行为不同于我的行为用户故事bdd场景(他们不应该谈论UI)。
对于DB,我会编写集成测试,以检查我的真实存储库是否能够在DB上读写内容。
最后我会写一些端到端的测试来检查连接在一起时一切正常。
答案 2 :(得分:1)
模仿的内容取决于架构。对于MVVM,您可以模拟模型以测试视图模型。对于MVP,您可以模拟视图和/或模型以测试演示者。如果您想编写端到端测试而不是单元测试,那么您可以通过视图模型/演示者测试应用程序的另一端(服务/数据库层)。