避免在Gherkin中重复自己

6

我已经使用specflow一段时间了,有些事情一直在困扰着我。

以下是我们目前正在使用的一个场景示例:

Scenario: Select a region via selection button
    When I select "Scotland" from Available Regions
    And I click on the "Select One" button
    Then Available Regions does not contain "Scotland"
    And Selected Regions contains "Scotland"

有没有办法避免在几乎每一行都说“苏格兰”?还是这样更易读,我应该坚持使用它?

4个回答

7

在我回答你的问题之前,我建议你花一分钟去阅读丹·诺斯(Dan North)的谁拥有这个领域

首先,我想摆脱这句话:然后我点击“选择一个”按钮,因为我认为这应该隐含在当我从可用地区中选择“苏格兰”时中。

现在你有:

Scenario: Select a region 
    When I select "Scotland" from Available Regions
    Then Available Regions does not contain "Scotland"
    And Selected Regions contains "Scotland"

而且你可以将它写成

Scenario: Select a region 
    When I select "Scotland" from Available Regions
    Then Available Regions does not contain the last selected region
    And Selected Regions contains the last selected region

有很大的区别吗?可能没有。

我发现随着我花更多时间接触黄瓜,它有助于像重构代码一样重构场景。在C#/SpecFlow中,我们可以实现

    Then Available Regions does not contain "Scotland"

    [Then("Available Regions does not contain (.*)")]
    public void ThenAvailableRegionsDoesNotContain(string region)
    {
        AvailableRegions.Contains(region).ShouldBeFalse();
    }

    Then Available Regions does not contain the last selected region

    [Then("Available Regions does not contain the last selected region")]
    public void ThenAvailableRegionsDoesNotContainLastSelectedRegion()
    {
        ThenAvailableRegionsDoesNotContain(LastSelectedRegion);
    }

这实际上取决于你。你喜欢哪种方言。


我同意你关于 And I click on the "Select One" button 的观点,但是我有另一个场景,基本上相同,但是使用的是 I double click on "Scotland" from Available Regions,这样可以区分测试。我同意你的观点,但是“最后选择的地区”并没有太大的改进。+1 for the link. - Mark Broadhurst
+1. 我也尽量避免使用“点击”和“按按钮”等词语。我个人会将每一行都保留为“Scotland”,因为当测试失败时,它是明确的,并且更容易找出失败的原因。 - marto
单击和双击都是用户界面操作,会引起某种操作。这种情况似乎属于操作领域而不是UI领域,因此我建议您使用像选择和编辑这样的术语(假设双击会导致编辑)。对于确认单击和双击映射到选择和编辑操作(或它们的模拟)的另一组测试没有任何问题,但是当您以这种方式工作时,它严重有助于隔离测试的脆弱性。希望能有所帮助。 - AlSki
双击也是一种选择选项,即用户可以双击其选择或选择它并按选择按钮。它们是相同的用户操作,可以用两种不同的方式应用。这可能涉及到UI领域。 - Mark Broadhurst

2
我建议修改这个场景的标题。“选择地区”并不能真正告诉你这个例子会发生什么。它可能是一些复杂的行为,在你选择一个地区时被触发,或者只是一个微小的UI细节,比如所选地区从可用地区移动到所选地区列表。
如果我正确理解了你的例子,那么我建议使用类似下面的标题:
Scenario: Selected region should be moved from available to selected regions

我认为拥有更富表现力的标题有两个优点:

1)当您在寻找某个详细信息时,您可以更快地导航并在您的活体文档中找到相关示例:阅读富表现力的标题总比阅读整个示例并反向工程其意图要快。

2)对于更复杂的场景(这个示例似乎不是),一个传达场景意图的富表现力标题可以帮助读者更快地理解场景的细节。

为了使场景更有趣,我会将断言组合成一步,因为您实际上想要断言所选项目已从可用列表移动到所选列表中:

Scenario: Selected region should be moved from available to selected regions
  When I select "Scotland" from "Available Regions"
  Then "Scotland" should be moved from "Available Regions" to "Selected Regions"

我认为这很接近我在对话中向某人解释此细节的方式。我不介意在这里重复“Scotland”,尽管一些人可能更喜欢用“所选地区”代替“Scotland”,正如AlSki已经指出的那样。这是一个品味问题,我通常会尝试听取有关情景的实际用词,这应该始终在记录之前发生。

作为一个小注释,我想提到的是,我有这样的印象,这是一个涉及相当低级别UI细节的情景。如果选择特定区域(如果选择区域具有任何特定业务相关性)会产生什么更高层次的影响,我会更感兴趣。如果您真的想描述和自动验证这样一个低级UI细节的情况,我会考虑在我表述情景时也显示出来。

Scenario: Selected region should be moved from available to selected regions list
  When I select "Scotland" from the "Available Regions" list
  Then "Scotland" should be moved from the "Available Regions" to "Selected Regions" list

当然,我现在假设你描述的是一个列表的详细UI行为,因为你在原始情境中没有提到列表。如果你所描述的不是关于UI的,那么情境应该用不同的措辞来更好地表达这一点。

2

有趣的例子!

正如其他人所说,通常建议在场景中避免实现细节 - 这就是步骤定义的用途。但你已经知道这个。

那么我要问的问题是:你想向谁证明这种行为?谁对通过正式测试可以单击按钮或双击感兴趣?如果你的答案不是“没有人”,那么也许适用以下情况:

"当编写此场景时,你可以想象利益相关者可能并不关心...一旦我们开始引入选项...详情...突然变得有趣...

此时,我期望该场景会补充一些更精细、或者更低级别的场景,每个场景描述不同的[选项]。这些新场景将针对不同的利益相关者。"

来自Dan North的“Whose Domain Is It Anyway?”的评论

也许你希望将场景以两种形式编写:一个更高层次的场景,仅演示用户可以选择业务区域(如何并不重要),另外两个面向不同利益相关者的场景显示不同的选择方法。

因此,一旦你决定你所做的是有价值的,我可能会重复“Scotland”(对于单个值的表格来说过于繁琐)。

稍微有些不同的是,我也建议:

Then Available Regions should not contain "Scotland"
And Selected Regions should contain "Scotland"

嗨Tom Tom,你说得很好。产品负责人正在逐渐理解TDD的概念,所以我敢打赌她只对高层次感兴趣,就像你建议的那样,坚持测试大多数低层次情况(不同类型的选择方法),但个别数据元素(在这种情况下是苏格兰)并不重要。你提到的值的缺失以及它已经移动到正确的位置也是一个很好的观点。 - Mark Broadhurst
如果她想要的话,这很值得! - Tom Tom
最好的情况也只有五五开,但她掌控着一切。 :-) - Mark Broadhurst

1

虽然我同意 @AlSki 的观点,认为进行一些重构是个好主意,但你可以使用 Examples 语法来多次使用相同的值:

Scenario Outline: Select a region
  Given do this "<value>"
  And do that "<value>"
  When we perform "<value>"
  Then we get "<value>"
Examples:
  | value    |
  | Scotland |

您还可以将多个条目添加到表中,以便每次使用不同的值运行相同的测试多次:

...
Examples:
  | value    |
  | Scotland |
  | England  |
  | Wales    |

这里有一个例子,它包含多个值,使您能够执行以下操作:

Scenario Outline: Select a region
  Given do this "<value>" with "<area>"
  And do that "<value>"
  When we perform "<value>"
  Then we get "<result>"
Examples:
  | value    | area   | result |
  | Scotland | North  | 40     |
  | Scotland | South  | 100    |
  | England  | West   | 200    |
  | England  | North  | 180    |

一个只有一个示例的场景大纲会让读者觉得过于技术化和乏味(请记住,Cucumber是一种沟通工具,而不是脚本语言)。 - jbpros
@jbpros 这仅仅是为了说明概念而已。 - dave.c
嗨,dave.c,感谢您的输入。我知道场景大纲/模板,虽然我同意它可以使示例更加DRY,但我认为在一个示例中失去可读性并不值得。但是,如果我有多个示例,那么是的,完全正确。 - Mark Broadhurst

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