在库/ API 代码中使用测试驱动开发 (TDD),在集成测试中使用行为驱动开发 (BDD) 是有意义的吗?

5
我是一个完全的BDD新手,我想了解BDD在开发周期中的作用。在TDD方法中,我们通常会为库或API编写单元测试,模拟对象,这样做非常好,因为它甚至可以驱动我们的设计。这些测试将在实际代码之前编写,这很好。
我知道BDD更多关于规范/场景测试,我可以看到它非常适合针对实际代码测试业务需求。但是编写这些测试的最佳实践是什么呢?我们是否仍然保持编写单独的测试(如TDD),模拟依赖项并为可能出错的每个事物编写单元测试?然后编写我们的BDD测试?我们首先编写BDD测试吗?我们是否只编写针对单个组件的BDD测试?
我使用.NET,并通常编写asp.net mvc应用程序,但这更多是一个理论问题,与底层编程语言无关。
非常感谢。
3个回答

6
不知道正确的方法,但这是我的经验。在分析规范文档后,我尝试提取尽可能多的不同“故事”,并使用BDD故事文件来描述它们。正如您已经知道的那样,每个句子都应该以三个关键字之一给定(given),当(when)然后(then)开始。
将整个规范翻译成BDD测试故事后,我编写了一个实现步骤的类,即执行故事中使用的每个句子。
下一步是开始编写一个实现,该实现将被调用以执行脚本语句,通过设置初始状态(given)、状态转换(when)和检查应用程序的目标状态(then)。
每当我需要实现一个实际的类方法时,我使用TDD进行彻底的隔离测试。
当然,为了运行测试代码的部分还没有实现,可以暂时模拟。

1
我会以同样的方式做。这也被称为ATDD验收测试驱动开发 +info http://www.methodsandtools.com/archive/archive.php?id=72 - Asier Barrenetxea

2

BDD是一组模式,围绕着描述和构建系统行为模型(以及更高层次的项目愿景),可以帮助我们就不同粒度的行为进行对话。

我们使用对话模式,例如“给定一个上下文,当发生这个事件时,应该出现这个结果”,并鼓励提出问题,例如“应该吗?总是吗?还有其他我们忽略的上下文吗?”

我们可以在单元级别、场景级别甚至分析空间中进行。

我倾向于从最高层次向内部工作。这里是我写的一篇文章,描述了从项目愿景到单元测试的全貌。

我编写的第一段代码将是场景。这里有一些场景,没有任何BDD框架,只是普通的NUnit,展示了如何使用领域语言使这些场景可读性更强。

我首先从用户界面开始。这可以是GUI、网页或另一个系统的接口,用于使用我的系统。完成后,我可以获得用户喜欢它的反馈。我经常硬编码数据等,只是为了获得反馈。

一旦我大致知道我的GUI会是什么样子,我就可以开始创建它背后的行为。我通常从控制器的行为开始。我会编写描述类的行为和责任的类级别示例。我使用模拟替代我尚未编写的协作类。这相当于TDD,但我编写的不是固定代码的测试,而是演示如何使用我的代码的示例,展示其行为方式和其价值,以便您可以安全更改它。我还使用给定/当/然后进行这个操作!但我倾向于使用更多的技术语言,并不担心它是否可读英文。我的Given / When / Then经常只在注释中出现。这里是同一代码库的类行为示例,所以您可以看到它们之间的区别。

希望这可以帮助您,祝您在BDD方面好运!


如果我理解正确的话,您首先会建立一个原型,展示它以获得反馈,然后再进行修改?这种方法可能适用于小型项目,但对于大型和复杂的项目来说是不好的。在这些项目中,原型被丢弃。此外,如果GUI很复杂,应该使用“presenter first”或MVC模式。 - BЈовић
“制造一个要丢弃的”模式在瀑布流开发模型中最为相关。如果代码被创建成易于更改的形式,您就不需要这样做,而BDD起源于敏捷实践(特别是XP和TDD)。这不是原型 - 这是真正的代码,我们现在已经在许多企业项目中使用了它。另外,请阅读我说“我通常从控制器的行为开始”的那一行 - 这应该告诉您我正在使用MVC。 - Lunivore
Lunivore,您能否就如何测试一个库项目(比如数学库)提供一些评论呢?该项目没有用户界面、数据库连接等,只是一个普通的库。对我来说,这个例子听起来非常适合使用TDD进行测试,您觉得呢?谢谢。 - Yannis
一个库通常仍然有一个类或一组类作为主要的“用户界面”,即使是另一个系统在使用它们。我会从“用户界面”编写场景,例如解决二次方程,然后为每个帮助增加这个场景的类编写单元级别的示例(测试,在TDD中),例如平方根、除法等。BDD不仅适用于场景级别,它也适用于单元级别——请参见我的类行为示例。顺便说一下,我的示例也是一个库——我通过提供使用它的代码库来展示如何使用它,这是另一种方式。 - Lunivore
BDD并不是真正专注于测试,而是专注于交流和发现。你会得到一些自动化的场景和例子作为一个很好的副产品,这真的很幸运! - Lunivore

0

你可以像使用TDD、单元测试或其他方式一样使用它。不同之处在于要测试"业务行为"。Spec Flow和Features是其中一种选择,单元测试语法看起来像这样:

[Given(@"a user exists with username ""(.*)"" and password ""(.*)""")]
public void GivenAUserExistsWithUsernameAdminAndPasswordPassword(string userName, string password) {

}

[Then(@"that user should be able to login using ""(.*)"" and ""(.*)""")]
public void ThenThatUserShouldBeAbleToLoginUsingAdminAndPassword(string userName, string password) {
        Assert.IsTrue(_authService.IsValidLogin(userName, password));
    }

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