如何提高SpecFlow/Gherkin步骤之间的可重用性?

Den*_*men 7 bdd acceptance-testing cucumber specflow gherkin

我想我完全理解SpecFlow背后的概念和想法,但即使阅读了Secret Ninja Cucumber Scrolls,The Cucumber Book,并且经历了各种论坛,我仍然不确定可重用性的途径.

我们的方案已经符合各种指南

  • 自我解释
  • 必须具有可理解的目的(使其与其他方案不同的原因)
  • 很独特
  • 表示垂直功能切片
  • 使用无所不在的语言
  • 从利益相关者的角度撰写
  • 关于业务功能,而不是软件设计
  • 由Epics组成
  • 不是测试脚本
  • 让其他人阅读它们以查看方案是否正确
  • 不引用UI元素
  • 代表关键的例子
  • 非技术
  • 精确且可测试
  • 尽可能重复
  • '给定'代表国家,而不是行动
  • '何时'代表行动
  • '然后'应代表一个明显的变化,而不是一些内部事件

我们的步骤必须遵守以下准则(一些特定于SpecFlow):

  • 使用无所不在的语言
  • 不引用UI元素
  • 不应该合并
  • 所有功能都应该是可重用的和全局的
  • 不应该链接到特定功能
  • 由实体,实体组或域概念分组
  • 不要创建在步骤定义文件中重用逻辑的步骤
  • 仔细考虑步骤所属的步骤文件
  • 不要在阶段之间重复使用步骤
  • 必须避免步骤中的文字字符串,但如果需要,请使用单引号
  • 切勿将多个[Given],[When]或[Then]属性应用于step方法
  • 根据它们代表的阶段订购步骤
  • 如果它对场景不重要,那么更重要的是不要提及它

但即使我们使用正则表达式占位符,我们仍然会得到相同步骤的大量变体.特别是如果某些事情不重要,你就不应该提到这些变化的规则.是的,在内部这些步骤重复使用,但不在场景中.

考虑例如以下场景:

Feature: Signing where both persons are physically available

@Smoke
Scenario: Show remaining time to sign based on previous signature
  Given a draft proposal
  And the first signature has been set
  When I try to set the second signature
  Then the remaining time to sign should be shown

@Smoke
Scenario: Re-signing of the first proposal
  Given a signature that has not been set within the configured time
  And the first signature has just been re-signed
  When I try to set the second signature
  Then the remaining time should start over
Run Code Online (Sandbox Code Playgroud)

将两个"给定"步骤合并为一个并放松一些可重用性会更好吗?

其他一些例子:

Feature: Conditionally show signatures to be signed

@Smoke
Scenario: Show the correct signature for a proposal with a night shift
  Given I have a proposal for the day shift
  When I change it to the night shift
  Then I should only be able to sign for the night shift

@Smoke
Scenario: Show additional signature when extending the shift
  Given I have a suspended proposal for the night shift
  When I extend the period to the day shift
  Then I should confirm extening the period over the shift
Run Code Online (Sandbox Code Playgroud)

我在这里错过了一个基本概念吗?

Gas*_*agy 12

这不是答案,而是一些提示:

  • 你可以在同一个方法上放置多个Given/When/Then属性.如果参数相同且差异仅在措辞中,则这可能很有用
  • 在许多项目中我们使用驱动程序/页面对象模式,因此步骤定义通常很短(2-3行),所以我们不太关心它们的数量
  • 我喜欢你的场景,我不会改变它们.另一方面,尝试着重于可读性而不是可重用性.如果您的语言一致,则可重用性将会出现.
  • 为了提高可重用性,尤其是当您正在讨论的实体有很多"变体"时,可以考虑使用步骤参数转换.这是一个例子:

你需要一个类来代表带有装饰的测试中的许可证:

class PermitDescription{
  bool suspended;
  bool draft;
}
Run Code Online (Sandbox Code Playgroud)

创建转换器方法:

[StepArgumentTransformation("permit")]
public PermitDescription CreateSimple(){
  return new PermitDescription();
}
[StepArgumentTransformation("draft permit")]
public PermitDescription CreateDraft(){
  return new PermitDescription() { draft = true; }
}
[StepArgumentTransformation("suspended permit")]
public PermitDescription CreateSuspended(){
  return new PermitDescription() { suspended = true; }
}
Run Code Online (Sandbox Code Playgroud)

您现在可以获得需要许可的更灵活的步骤定义:

[Given(@"I have a (.*) for the day shift")]
public void Something(PermitDescription p)
{ ... }
Run Code Online (Sandbox Code Playgroud)

匹配到:

Given I have a permit for the day shift
Given I have a draft permit for the day shift
Given I have a suspended permit for the day shift
Run Code Online (Sandbox Code Playgroud)

当然这是一种可以滥用的工具,但在某些情况下它可以提供帮助.