SpecFlow/Cucumber/Gherkin - 使用场景大纲中的表格

Mat*_*cey 17 automated-tests cucumber specflow gherkin

希望我能够清楚地解释我的问题,以便其他人理解,我们在这里,想象我有以下两个假设情景:

Scenario: Filter sweets by king size and nut content
Given I am on the "Sweet/List" Page
When I filter sweets by 
    | Field               | Value  |
    | Filter.KingSize     | True   |
    | Filter.ContainsNuts | False  |
Then I should see :
    | Value            |
    | Yorkie King Size |
    | Mars King Size   |

Scenario: Filter sweets by make
Given I am on the "Sweet/List" Page
When I filter sweets by 
    | Field        | Value  |
    | Filter.Make  | Haribo |
Then I should see :
    | Value   |
    | Starmix |
Run Code Online (Sandbox Code Playgroud)

这些场景非常有用,因为我可以在不改变相关编译测试步骤的情况下添加任意数量的Field/Value和Then值条目.但是,不同过滤器测试的复制/粘贴方案将变得重复并占用大量代码 - 这是我想要避免的.理想情况下,我想创建一个场景大纲,并保持我上面的测试的动态性质,但是当我尝试这样做时,我遇到了一个定义示例表的问题我不能添加新行,因为那将是一个新的测试实例,目前我有这个:

Scenario Outline: Filter Sweets 
Given I am on the <page> Page
When I filter chocolates by 
    | Field    | Value   |
    | <filter> | <value> |
Then I should see :
    | Output   |
    | <output> |
Examples:
    | page       | filter      | value  | output  |
    | Sweet/List | Filter.Make | Haribo | Starmix |
Run Code Online (Sandbox Code Playgroud)

所以我遇到的问题是能够动态地向我的过滤器添加行和使用场景大纲时的预期数据,是否有人知道这种方法?我应该从不同的角度接近这个吗?

解决方法可能是这样的:

Then I should see :
    | Output |
    | <x>    |
    | <y>    |
    | <z>    |
    Examples:
    | x | y | z |
Run Code Online (Sandbox Code Playgroud)

但那不是很有活力......希望有更好的解决方案吗?:)

Dar*_*ren 34

我不认为SpecFlow,Gherkin和开箱即用的Cucumber可以满足您的需求.我不能代表作者,但我敢打赌它故意不是以这种方式使用,因为它违背了编写和实现这些规范的整体"流程".在许多方面,规范对非程序员来说是可读的,为程序员提供指导,以实现与规范匹配的代码,进行集成测试,并在重构时提供一定数量的灵活性.

我认为这是一种情况,你感受到的痛苦是一个问题,但它可能不是你想的那个.你说:

"然而,不同过滤器测试的复制/粘贴方案将变得重复,并且会占用大量代码 - 我想避免这种情况."

首先,我不同意在写作中解释自己是"重复的",至少不过是重复使用"苹果,汽车等"这样的特定词语.一遍又一遍地.问题是:这些话是否正确解释了你在做什么?如果它们是,并且解释您的情况需要您写出多个场景,那就是它所需要的.沟通需要语言,有时也需要相同的语言.

事实上,你所谓的"重复"是使用Gherkin和Cucumber或SpecFlow等工具的好处之一.如果你能够反复使用那个句子,那就意味着你不必一遍又一遍地编写测试代码.

其次,你确定你正在编写正确的规范吗?我只是因为如果场景的数量变得无法控制,到了你有这么多人无法遵循你所写的内容的程度,你的规范可能不是针对正确的事情.

一个可能的例子可能是你在这个场景中测试过滤分页的方式.是的,您希望您的规格涵盖所有功能,并且您的网站将在与您的过滤相同的页面上进行分页,但代价是什么?需要经验和实践才能知道什么时候放弃所谓的"理想"的无嘲化,完全集成测试会产生更好的结果.

第三,不要认为规范是针对每种可能情景的完美覆盖.场景基本上是状态的快照,这意味着有些功能可以覆盖无限大的场景,这是不可能的.所以你会怎么做?编写能够最好地讲述故事的功能.甚至让故事推动发展.但是,除了规格之外,不会转换为您的规格或其他情况的细节最好留给直接TDD.

在您的示例中,您似乎基本上讲述了一个允许用户创建针对糖果和糖果的动态搜索的网站的故事.他们输入一组可能的搜索条件,单击按钮,然后获得结果.坚持下去,只写出足够的规格来完成故事.如果您对覆盖范围不满意,请使用更多规格或单元测试进行清理.


无论如何,这只是我的想法,希望它有所帮助.

  • Darren,非常感谢你的评论,我对BDD很新,他们非常乐于助人,我同意你所写的内容,特别是第三部分.我已经标记了你的答案,但是给了帕特里克解决方案,因为他为原始问题提供了技术解决方案.再次感谢. (2认同)

pat*_*raw 7

从技术上讲,我认为您可以尝试从步骤定义中调用步骤:

从步骤定义调用步骤

例如,我认为你可以改写

Then I should see :
| Output   |
| <output> |
Run Code Online (Sandbox Code Playgroud)

要成为一个自定义的步骤

I should have output that contains <output>
Run Code Online (Sandbox Code Playgroud)

其中output是逗号分隔的预期值列表.在自定义步骤中,您可以将逗号分隔列表拆分为数组并迭代调用

Then "I should see #{iterated_value}"
Run Code Online (Sandbox Code Playgroud)

您可以使用类似的技术传入过滤器和过滤器值列表.您测试特大号测试的示例行可能如下所示

| page       | filter                               | value       | output                           |
| Sweet/List | Filter.KingSize, Filter.ContainsNuts | True, False | Yorkie King Size, Mars King Size |
Run Code Online (Sandbox Code Playgroud)

或者可能

| page       |                              filter-value-pairs | output                           |
| Sweet/List | Filter.KingSize:True, Filter.ContainsNuts:False | Yorkie King Size, Mars King Size |
Run Code Online (Sandbox Code Playgroud)

话虽这么说,你也许应该把达伦的话牢记在心.我不确定这种方法是否有助于实现非开发人员可读的场景的最终目标.