Cucumber - 如何构建测试步骤?

Cucumber - How to struct your tests steps?

我目前正在学习黄瓜,在非常简单的测试中,我有一些疑问: “组织我的 StepClasses 的最佳方式是什么。

这是我的.feature:

Feature: How many potatoes have in the sack

Scenario: I put one potato in the Bag
    Given the bag has 10 potatoes
    When I put 1 potato
    Then I should be told 11 potatoes

  Scenario: I remove one potato from the Bag
    Given the bag has 10 potatoes
    When I remove 1 potato
    Then I should be told 9 potatoes

还有我的 StepClass:

public class Stepdefs {

private Integer potatoesInTheBag;

@Given("^the bag has 10 potatoes$")
public void the_bag_has_10_potatoes(){
    this.potatoesInTheBag=10;
}

@When("^I put 1 potato$")
public void i_put_one_potato(){
    this.potatoesInTheBag = potatoesInTheBag + 1;
}

@Then("^I should be told (\d+) potatoes$")
public void i_should_be_told_potatoes(int potatoes) throws Exception {
    assertEquals(potatoesInTheBag.intValue(),potatoes);
}

@When("^I remove 1 potato$")
public void i_remove_one_potato(){
    this.potatoesInTheBag = potatoesInTheBag - 1;
}

}

这个例子工作正常,但 i_remove_one_potato() 应该留在此处,还是在另一个步骤 class 中? 另一个问题,如果我想使用场景大纲,在这种情况下我会怎么做?因为虽然土豆 added/remove 是一样的,但答案会有所不同。 有一些好的实践可以指导构建黄瓜测试的过程?

感谢

关于如何构建特征文件和步骤定义有很多不同的意见,其中很多归结为偏好和项目的需要。我在这里的所有想法都是围绕通过浏览器对大型项目进行系统测试,这可能与每个人都不相关。

就是说,我在功能和步骤之间的 1 对 1 关系方面运气最好。我喜欢用一个步骤 def 来提供单个功能文件,并避免将重复使用步骤作为保持代码 DRY 的主要策略(这就是页面对象的用途!)。有时重用一个步骤是有意义的(例如,假设我已经登录),但我的经验是,它会导致构建这些包含非常小的原子步骤的大型库,这些步骤很难找到,也很难重用,并且把小黄瓜逼到极致

对 1 对 1 方法(除了违反黄瓜文档中的 this anti-pattern 之外)的明显抱怨是它会导致重复代码,但我发现你想要的任何东西do more than once 可能是可以下推到页面对象的通用操作。除了特定于正在测试的业务规则的代码外,这在步骤定义中留下的内容很少,无论如何您都不需要复制这些代码。

如此简短的回答,我会将 i_remove_one_potato() 与该功能的其他步骤保持在相同的 class 中。但是就像你说的,你的例子很简单,所以我猜测你的项目最终的需求是什么。

例如大纲,你应该可以做类似的事情

Scenario Outline: I add/remove potatoes from bag
Given the bag has <initial> potatoes
When I <add_remove> <delta> potatoes
Then I should be told <outcome> potatoes
Examples:
| add_remove | initial | delta  | outcome |
| add        | 10      | 1      | 11      |
| add        | 10      | 10     | 20      |
| remove     | 10      | 1      | 9       |
| remove     | 10      | 10     | 0       |

虽然我尽量不过度描述场景大纲,但这可能太过分了。将整个功能归结为一个由通用步骤驱动的编程 table 可能很诱人,但在某些时候很难提取出单独的业务规则是什么。当一个例子开始失败时,你必须梳理整个事情并弄清楚为什么作者选择了他所做的 table 值。 BDD 工具应该阐明该功能,而大的 table 往往会掩盖它。对于上面的示例,我可能应该将添加和删除分成单独的大纲,所以我不会将不同业务规则的示例混合在一起。

一些想法!祝你好运!

只要步骤与要测试的场景相关,最好在单个步骤 Class 文件中找到步骤。对于场景大纲,它可能是这样的:Add/Remove potatoes from bag.

:在类似的场景中使用变量 假设袋子里有“10”个土豆 而不是您使用的那个将有助于长期 运行。