确定 BDD 场景中适当的详细程度
Determining the proper level of detail in a BDD scenario
我是 BDD 的新手,正在尝试使用它来充实新项目的功能规范。
您在网上看到的大多数示例在细节方面看起来都非常简单和轻松。我很难知道在场景中包含什么是重要的,什么不应该包含。
例如,给定如下标题:用户登录
场景 1:用户使用有效凭据登录
给定 显示登录页面
当用户输入用户名和密码时
并且用户提交请求
然后 用户被定向到主页
我不明白的是,如果用户已被管理员禁用或由于密码尝试失败次数过多而被锁定怎么办等等。那些是单独的场景吗?如果是这样,场景 1 是否需要表明此用户 not 已禁用且 not 已锁定出去?
后端发生的事情——即客户端希望系统记录每个用户登录——是否包含在场景中?我读过的大多数内容听起来好像 BDD 应该专注于用户与系统的交互。
如果您在后端包含登录之类的内容——那么在登录尝试失败时增加登录失败计数器之类的内容呢?这似乎更像是一个技术细节——那么如果需要锁定功能,它在哪里得到记录?
如您所见,我很难决定在哪里划定 BDD 场景范围的界限。
感谢您帮助我们更好地理解!
场景中应该包含哪些上下文?
我发现不将场景视为测试,而是将其视为有助于说明系统行为方式及其价值的动态文档,这会有所帮助。
如果您可以判断用户在第一种情况下没有被锁定并且没有被禁用,那么您就不需要包括这些步骤。
对于使用活跃的、启用的帐户登录之类的事情,这是显而易见的,但对于保持在交易限额内的交易者或胎儿心跳 运行 以健康的速度,这可能不是这样,或尚未达到报告阈值的评论。您可以决定是否实用地包含这些类型的上下文。
不过,我更喜欢将 不会更改 或不经常更改的文档(例如核心领域概念)移到场景之外。也许它可以在场景文件顶部的简介中,或者在新加入者在编码之前可以阅读的某个团队 wiki 上。不一定要出现在场景中。
(显然,您需要包括在任何失败场景中导致失败的上下文!)
副作用和其他结果如何?
所有 重要的结果之所以如此,是因为在某些时候,它们变得可见或产生的影响超出了场景中行为所涵盖的系统。
例如,当我从提款机取钱时,我的账户也会被扣款。我可能不认为这是行为的一部分,但它确实必须发生。那是因为场景中还涉及另一个利益相关者——银行。
或者,当 Fred 收到微波炉退款时,微波炉会重新入库并且库存数量会增加。 Fred、收银员和库存管理员都是这里的利益相关者。
在我们向日志中添加内容的情况下,利益相关者会将这些日志用于其他用途。了解该价值可以帮助我们弄清楚我们为什么要记录日志,并从发现它有价值的利益相关者的 POV 中描述该结果。
如果结果可以独立交付并且仍然有价值,它们可以出现在不同的场景中。我对此非常务实,所以我可能会将它们放在相同的场景中,然后在 "stock control" 场景的数量意味着它可能应该有自己的功能文件后重构它们。
如果结果 不能 独立运送,这通常是任何交易的情况,我希望看到这些结果至少在一种情况下一起出现,以使很明显他们是相关的。他们不必出现在每个场景中。例如,一旦我们编写了用户没有资金因此他们的帐户 不会 被扣款的场景,我们可能不必在任何情况下再次提及该帐户其他提现失败场景
这种多利益相关者的观点也与 "Outside-In" 的 BDD 概念相关,其中我们添加到系统中的所有行为都是为了通过某些接口为某些利益相关者提供价值。
与其他用户或时间的互动如何?
有时 - 非常偶尔 - 我们需要多个 when 来描述正在发生的事情,并且登录计数器递增的示例非常适合使用。
登录计数器的值是仅它会在 3 次尝试后禁用帐户(例如)。它本身没有任何价值。这是一个实现细节。如果我们将其作为场景中的结果,我们就会将自己与该实现耦合,这不会很好。因此,有两种情况 - 一种描述登录计数器的工作原理,另一种说明它为何有价值 - 感觉不对,因为其中一种没有描述有价值的行为:
Given Clarence logged in successfully last time
When Clarence enters his password incorrectly
Then the login counter should be incremented.
Given Clarence's login counter was incremented twice
When Clarence enters his password incorrectly
Then his account should be disabled.
呸。我们不要那样做。
该计数器的唯一值来自克拉伦斯的行为与克拉伦斯未来(或过去)行为的相互作用。所以我们可以有这样的东西:
Given Clarence logged in successfully last time
When he enters his password incorrectly
And enters his password incorrectly
And enters his password incorrectly
Then his account should be disabled.
当然,这有点啰嗦,所以我们可能会说:
Given Clarence logged in successfully last time
When he enters his password incorrectly 3 times
Then his account should be disabled.
我们可以做到这一点,因为这是同一回事。有些互动虽然涉及不同的事情发生("time passing" 是我经常遇到的另一种)。
Given Clare is editing trade 12345
When Stephen edits and saves that trade
And Clare tries to save that trade
Then she should be told that Stephen has already edited it.
当然,在这种情况下,克莱尔的互动与斯蒂芬的互动不同,因为她的拯救尝试失败了。
注意这里使用tries表示失败;我如何使用假设的另一个例子。如果它没有说 tries 我们可以假设事件成功。备选方案是:
When Clare saves the trade successfully
除非成功的结果令人惊讶而不是常态,否则这会有点重复,所以我更喜欢默认不使用任何东西,而 尝试 失败。从自动化的角度来看,区分它们很重要,因为它可以让我们做一些事情,比如将自动化工作流程移动到错误页面而不是确认页面。
读起来也很不错。这几乎就是我们尝试使用这些英语语言工具的原因。
我是 BDD 的新手,正在尝试使用它来充实新项目的功能规范。
您在网上看到的大多数示例在细节方面看起来都非常简单和轻松。我很难知道在场景中包含什么是重要的,什么不应该包含。
例如,给定如下标题:用户登录
场景 1:用户使用有效凭据登录
给定 显示登录页面
当用户输入用户名和密码时
并且用户提交请求
然后 用户被定向到主页
我不明白的是,如果用户已被管理员禁用或由于密码尝试失败次数过多而被锁定怎么办等等。那些是单独的场景吗?如果是这样,场景 1 是否需要表明此用户 not 已禁用且 not 已锁定出去?
后端发生的事情——即客户端希望系统记录每个用户登录——是否包含在场景中?我读过的大多数内容听起来好像 BDD 应该专注于用户与系统的交互。
如果您在后端包含登录之类的内容——那么在登录尝试失败时增加登录失败计数器之类的内容呢?这似乎更像是一个技术细节——那么如果需要锁定功能,它在哪里得到记录?
如您所见,我很难决定在哪里划定 BDD 场景范围的界限。
感谢您帮助我们更好地理解!
场景中应该包含哪些上下文?
我发现不将场景视为测试,而是将其视为有助于说明系统行为方式及其价值的动态文档,这会有所帮助。
如果您可以判断用户在第一种情况下没有被锁定并且没有被禁用,那么您就不需要包括这些步骤。
对于使用活跃的、启用的帐户登录之类的事情,这是显而易见的,但对于保持在交易限额内的交易者或胎儿心跳 运行 以健康的速度,这可能不是这样,或尚未达到报告阈值的评论。您可以决定是否实用地包含这些类型的上下文。
不过,我更喜欢将 不会更改 或不经常更改的文档(例如核心领域概念)移到场景之外。也许它可以在场景文件顶部的简介中,或者在新加入者在编码之前可以阅读的某个团队 wiki 上。不一定要出现在场景中。
(显然,您需要包括在任何失败场景中导致失败的上下文!)
副作用和其他结果如何?
所有 重要的结果之所以如此,是因为在某些时候,它们变得可见或产生的影响超出了场景中行为所涵盖的系统。
例如,当我从提款机取钱时,我的账户也会被扣款。我可能不认为这是行为的一部分,但它确实必须发生。那是因为场景中还涉及另一个利益相关者——银行。
或者,当 Fred 收到微波炉退款时,微波炉会重新入库并且库存数量会增加。 Fred、收银员和库存管理员都是这里的利益相关者。
在我们向日志中添加内容的情况下,利益相关者会将这些日志用于其他用途。了解该价值可以帮助我们弄清楚我们为什么要记录日志,并从发现它有价值的利益相关者的 POV 中描述该结果。
如果结果可以独立交付并且仍然有价值,它们可以出现在不同的场景中。我对此非常务实,所以我可能会将它们放在相同的场景中,然后在 "stock control" 场景的数量意味着它可能应该有自己的功能文件后重构它们。
如果结果 不能 独立运送,这通常是任何交易的情况,我希望看到这些结果至少在一种情况下一起出现,以使很明显他们是相关的。他们不必出现在每个场景中。例如,一旦我们编写了用户没有资金因此他们的帐户 不会 被扣款的场景,我们可能不必在任何情况下再次提及该帐户其他提现失败场景
这种多利益相关者的观点也与 "Outside-In" 的 BDD 概念相关,其中我们添加到系统中的所有行为都是为了通过某些接口为某些利益相关者提供价值。
与其他用户或时间的互动如何?
有时 - 非常偶尔 - 我们需要多个 when 来描述正在发生的事情,并且登录计数器递增的示例非常适合使用。
登录计数器的值是仅它会在 3 次尝试后禁用帐户(例如)。它本身没有任何价值。这是一个实现细节。如果我们将其作为场景中的结果,我们就会将自己与该实现耦合,这不会很好。因此,有两种情况 - 一种描述登录计数器的工作原理,另一种说明它为何有价值 - 感觉不对,因为其中一种没有描述有价值的行为:
Given Clarence logged in successfully last time
When Clarence enters his password incorrectly
Then the login counter should be incremented.
Given Clarence's login counter was incremented twice
When Clarence enters his password incorrectly
Then his account should be disabled.
呸。我们不要那样做。
该计数器的唯一值来自克拉伦斯的行为与克拉伦斯未来(或过去)行为的相互作用。所以我们可以有这样的东西:
Given Clarence logged in successfully last time
When he enters his password incorrectly
And enters his password incorrectly
And enters his password incorrectly
Then his account should be disabled.
当然,这有点啰嗦,所以我们可能会说:
Given Clarence logged in successfully last time
When he enters his password incorrectly 3 times
Then his account should be disabled.
我们可以做到这一点,因为这是同一回事。有些互动虽然涉及不同的事情发生("time passing" 是我经常遇到的另一种)。
Given Clare is editing trade 12345
When Stephen edits and saves that trade
And Clare tries to save that trade
Then she should be told that Stephen has already edited it.
当然,在这种情况下,克莱尔的互动与斯蒂芬的互动不同,因为她的拯救尝试失败了。
注意这里使用tries表示失败;我如何使用假设的另一个例子。如果它没有说 tries 我们可以假设事件成功。备选方案是:
When Clare saves the trade successfully
除非成功的结果令人惊讶而不是常态,否则这会有点重复,所以我更喜欢默认不使用任何东西,而 尝试 失败。从自动化的角度来看,区分它们很重要,因为它可以让我们做一些事情,比如将自动化工作流程移动到错误页面而不是确认页面。
读起来也很不错。这几乎就是我们尝试使用这些英语语言工具的原因。