【问题标题】:Avoiding repeating yourself in Gherkin避免在 Gherkin 中重复自己
【发布时间】:2013-03-01 06:04:26
【问题描述】:

所以我使用 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"

是否有避免在几乎每一行都说“苏格兰”的方法? 还是让它更具可读性,我应该坚持下去?

【问题讨论】:

    标签: cucumber specflow gherkin


    【解决方案1】:

    在我尝试回答您的问题之前,我建议您花点时间阅读一下 Dan North 的Who's domain is it anyway

    所以首先我想去掉And I click on the "Select One" button 的行,因为我认为它应该隐含地成为When I select "Scotland" from Available regions 的一部分。

    现在你有

    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
    

    有很大的不同吗?好吧,可能不是。

    我在 Cucumber 上花费了更多时间后发现,它有助于重构场景,就像重构场景背后的代码一样。在 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);
        }
    

    老实说,这取决于你。你喜欢哪种方言

    【讨论】:

    • +1 链接。我同意你对And I click on the "Select One" button 的看法,但我有另一个场景,它基本相同,但I double click on "Scotland" from Available Regions 区分了测试。我同意你的观点,但“最后选择的地区”并不是一个巨大的改进。
    • +1。我也尽量避免点击和按下按钮之类的词。我个人会将每一行都保留为“苏格兰”,因为当测试失败时,它是明确的,并且更容易找出失败的原因。
    • 单击和双击都是导致操作的用户界面操作。这种情况似乎是在操作域而不是 UI 域中,​​因此我建议您使用诸如选择和编辑之类的术语(假设双击会导致编辑)。有另一组测试确认单击和双击映射到选择和编辑操作(或它们的模拟)并没有错,但是当您以这种方式工作时,它非常有助于隔离测试的脆弱性。希望对您有所帮助。
    • 双击也是一个选择选项,即用户可以双击他们的选择或选择它并按下选择按钮。它们是相同的用户操作,可以以两种不同的方式应用。它可能正在深入那里的 UI 域。
    【解决方案2】:

    有趣的例子!

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

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

    “在编写这个场景时,您可以想象利益相关者可能不太关心如何...... 一旦我们开始介绍选项......细节......突然变得有趣 ...

    在这一点上,我希望这个场景会增加一些更细粒度或更低级别的场景,每个场景都描述了我们支持的不同 [选项]。这些新方案将针对不同的利益相关者。"

    来自 Dan North 的“这到底是谁的领域”中的 cmets?

    也许您希望以两种形式编写场景:一个更高级别的只是演示用户可以为业务人员选择区域(如何无关紧要),另外两个,用于不同的利益相关者展示了不同的选择。

    所以,一旦你确定你所做的事情是值得的,我可能会重复“苏格兰”(这里的单个值的表是多余的)。

    另外,我还建议:

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

    【讨论】:

    • 嗨,Tom Tom,好点子,产品负责人正在掌握 TDD 的想法,所以虽然我敢打赌,她只对高级别感兴趣,因为您建议坚持最低级别案例(不同类型的选择方法)进行了测试,但单个数据元素(在这种情况下为苏格兰)不感兴趣。关于价值的缺失以及它已经移动到正确的位置,这是一个很好的观点。
    • 可以说,如果她想要的话,这是值得的!
    • 50/50 最多,但她确实做主。 :-)
    【解决方案3】:

    我建议修改这个场景的标题。 “选择一个地区”并没有真正告诉你,从这个例子中可以期待什么。它可能是在您选择区域时触发的一些复杂行为,或者是微小的 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"
    

    我认为这与我在对话中向某人解释这个细节的方式非常接近。我不介意在这里重复“苏格兰”,尽管有些人可能更喜欢用“所选地区”代替“苏格兰”,正如 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 行为,因为您没有在原始场景中编写列表。如果不是关于用户界面,也就是您所描述的内容,则应该对场景进行不同的表述以更好地表达这一点。

    【讨论】:

      【解决方案4】:

      虽然我同意 @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    |
      

      Here is an example 具有多个值,它允许您执行以下操作:

      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 这纯粹是为了说明这个概念。
      • 嗨 dave.c,感谢您的输入,我知道 Scenario Outline\Template 虽然我同意它会干掉这个例子,但我认为失去可读性并不值得一个例子。但是,如果我有多个示例,是的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-09
      相关资源
      最近更新 更多