你如何使用声明式验收测试来捕获需求?

7

背景

我正在尝试帮助我的团队为一个新的移动应用项目进行组织。我们选择遵循BDD(也可以参见BDD definition),以捕获每个单独用户故事的简单英语要求,这些要求形成了利益相关者和开发人员之间的合同。

我们使用验收测试来记录每个用户故事的要求。验收测试在冲刺计划之前编写。开发人员在冲刺计划期间完善并添加测试。

我们将验收标准定义为一系列规则(例如:输入验证、默认值等),将验收测试定义为Cucumber场景列表。我们计划使用Calabash进行移动测试。

我认为验收标准/测试是更敏捷且更好的解决方案,因此不需要更正式的需求文档。

我认为我已经找到了一个有效的解决方案,但我想了解其他人如何收集需求并编写验收测试。

问题

在Cucumber社区中,存在命令式声明式测试步骤的辩论。我倾向于使用命令式,因为开发者必须知道可交付的用户故事是什么样子。
我认为UI耦合(也称为脆弱测试)不是问题。有方法可以将UI与测试解耦(例如:页面对象)。我也不认为详细的步骤会使非技术利益相关者难以理解(除非他们不知道如何使用Web浏览器或移动设备,但这是另一个问题)。
我可能误用了“验收测试”这个术语。在我的使用中,验收测试不是与单元测试相同级别的范畴。我将验收测试视为高级集成测试示例
  • 作为一个访客
  • 我想要登录
  • 以便访问应用程序功能
命令式测试
  • 场景:有效登录
    • 假设我在“登录”屏幕上
    • 当我在“电子邮件”中输入“email@domain.com”
      • 并在“密码”中输入“password1”
      • 然后我点击“登录”
    • 那么我会看到“登录成功”
声明式测试
  • 场景:有效登录
    • 假设我有一个有效的账户
    • 那么我可以登录
这两个功能可以覆盖相同的功能,后者更短,但它并没有说我是否可以使用用户名、电子邮件或Facebook/Twitter/Google等帐户登录。这并不足以实际编写解决方案。
问题是如何使用声明性步骤捕获功能要求?

1
Dan North(BDD的创始人)对此有一些不错的想法:http://dannorth.net/2011/01/31/whose-domain-is-it-anyway/。需要记住的是,一个场景应该只涉及两个领域:使用该功能的用户和将要实现它的开发人员。场景应该向这两个领域澄清发生了什么以及如何发生(例如:“用户使用电子邮件和密码登录”,而不是“用户使用用户名和密码登录”等)。 - Brenden
据http://blog.cyrusinnovation.com/2013/04/improve-your-ios-frank-cucumber-acceptance-tests.html所述,当利益相关者关注给定场景的用户体验时,使用命令式语句是合适的。在追求简洁性的同时,通过声明式语句明确表达必要的命令式语句也是有意义的。 - Brenden
这个问题似乎与项目规划无关,因此我认为它应该迁移到programmers.stackexchange.com。 - Brenden
我认为这不是离题的,因为问题是关于命令式与声明式BDD测试的区别,而不是关于项目规划的。也许值得将问题标题改名? - Ben Smith
2个回答

6

写得很好的问题!

如何使用声明性步骤捕获功能的要求?

功能的要求记录在步骤定义中。

因此,在您的命令式示例中:

When I enter "email@domain.com" in "email"
And I enter "password1" in "password"
And I tap "login"

通过重新编写,这可以变得更加声明性:

Given I login using valid credentials

在此场景语句的步骤定义中,可以实现导航到有效帐户(即实施定义“有效”意味着什么的验收标准)的步骤。相同的适用于相反的情景。
Given I login using invalid credentials

实现满足验收标准的这种情景的步骤可以在底层的步骤定义中实现。

采用这种声明性方法意味着你会失去来自功能需求的指令(即需要执行哪些确切的步骤),使商业部门难以仅通过读取特性文件就能看到这些方案的确切操作。然而,你所获得的是测试变得不那么脆弱,因为实现任务的具体步骤记录在步骤定义中,并且这个步骤定义可以被多个特性共享。

在我们公司,我们也面临着同样的问题,我们发现在某些情况下,使用命令式而不是声明式更好,反之亦然。例如,在你的情况下,“Given I have a valid account”组成的步骤可能在许多特性中使用,因此将其声明性地写出是合理的。然而,如果有一个特性涉及输入许多不同的字符串值,那么在这种情况下最好写出命令式的表达方式。

"因地制宜!"

从 SO 社区获得其他答案对于这个问题非常有趣。


1
另外,您可以在场景标题中添加关于验收标准的“恰好足够”的细节。因此,在您的示例中,您可以有“场景:仅使用视网膜扫描登录”和“场景:使用电子邮件和密码登录”。 - Ben Smith
这是正确的,但将其作为单独的用户故事是否更好(例如:一个用于电子邮件/密码,一个用于Facebook登录,一个用于视网膜扫描)? - Brenden
1
是的,我同意。我为糟糕的示例道歉!我应该说的是“场景:使用有效电子邮件和无效密码登录”,“场景:使用无效电子邮件和有效密码登录”以及“场景:使用有效电子邮件和密码登录”。 - Ben Smith
@Brenden 回答已经更新。希望我已经更新了我们对话的要点! - Ben Smith
1
我很高兴有人问了这个问题,因为我也遇到了同样的问题。 - msmith1114
显示剩余3条评论

2
我最近去了一家店或者网上购买洗衣机和洗碗机。我只想购买一个用水更少、洗涤更快的产品。但是,我遇到的细节非常多:如转速、内桶厚度、总连接负载等。
虽然从简单的例子中可以看出命令式风格似乎很合适,但实际上它会使阅读场景更加困难和无聊。如果你在一个你没有直接参与技术/日常层面的项目中阅读10个场景,你就会有这种体验。
鉴于使用黄瓜的目标之一是为整个项目带来透明度,特别是针对非技术用户,声明式风格更能让管理层积极参与。我在我的项目中看到过这种情况。
这里是一个虚构的故事。试着用命令式风格实现它,几天后回来再读一遍,你会发现它太无聊了。
Feature: Delivery 
    Free delivery is offered to customers who order two or more items

  Scenario Outline: Calculate postage for delivery
    Given I am signed-in
    When I "<order>" items
    Then postage should be "<postage>"   

    Examples:
    | order | postage |
    | 1     | 0.99    |
    | 2     | 0       |
    | 3     | 0       |
    | 0     | ?       |

您可能希望阅读另一个链接——如何在不自我毁坏的情况下实现UI测试?

该链接与IT技术有关,请参考。请注意:请勿删除HTML标签。


很好的说明,但在这个例子中,真正的问题是指定什么是已登录状态,在下单时需要的货币邮费以及邮寄地区/国家。就像我在我的问题中提到的那样,我想知道当你使用声明性步骤时,在哪里定义实现的要求。谢谢。 - Brenden

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