使用效果图和示例规范进行敏捷项目规划 - 第二部分
关于使用效果图和示例规范作为项目规划工具的系列文章的第二部分,共两部分。第二部分侧重于规范。
规范是一组业务规则,附带示例,用于捕捉定义功能如何实现的所有场景和有意义的边缘情况。它们以一种可以自动化的方式编写,并在开发过程中持续针对代码库运行,这有助于突出围绕对问题空间的共同理解的任何潜在问题。
在我之前的文章中,我讨论了创建效果图以规划项目的高级功能。一旦创建了效果图,您就会得到一堆功能和一个粗略的优先级顺序,您可以使用它来进行规划和调度。这些功能本身可以以这种方式充实,从而从业务角度提供系统应该如何工作的蓝图。回到我们的老朋友,Acme Inc. 及其机器人宠物,团队认为新客户是最高优先级,因为任何描述的宠物都是终身的,而且机器人宠物很可能比它们的主人活得更久(它们应该至少比其 12 个月的保修期活得更久)。他们决定首先专注于浏览目录,并准备编写他们的第一个功能。由于他们是微软的拥护者,他们正在使用 SpecFlow,但也可以使用其他工具,例如 Cucumber。底层语言 (Gherkin) 对于两者来说都是相同的。启动 Visual Studio,他们将 PetSearchFeature.feature
添加到他们的验收测试项目中。
一个功能基本上是场景的集合,带有示例,用于捕捉某个功能部分的业务需求。它们本质上成为活的文档,真正代表了系统的当前功能状态,前提是它们随着系统的发展而发展。每当您编写一个场景时,SpecFlow 都会在其知道的位置(带有功能的程序集,除非您告诉它在其他地方查找)搜索带有 Binding
属性修饰的类,并从这些类中查找其属性与场景语句中的文本匹配的方法。例如,这里是 Acme 的宠物搜索功能
Feature: Search for pets
In order to narrow down my purchase options
As a site visitor
I want to be able to search the catalogue for my perfect robot pet
Background:
Given a pet catalog containing
| Size | Price | Type | Pet Breed |
| Small | 100 | Cat | Siamese |
| Small | 150 | Cat | Burmese |
| Small | 200 | Cat | Siamese |
| Large | 200 | Dog | Boxer |
| Large | 250 | Dog | Sheepdog |
| Large | 500 | Primate | Chimpanzee |
| Large | 550 | Primate | Gorilla |
Scenario: All search criteria are combined when searching
Given the following search criteria
| Max Price | Type | Breed |
| 150 | Cat | Siamese |
When all criteria are used to search the catalog
Then the results are filtered by price
And the results are filtered by type
And the results are filtered by breed
And the following pets are found
| Size | Price | Type | Pet Breed |
| Small | 100 | Cat | Siamese |
Scenario: Searching using Max Price
Given I search using a Maximum Price of 150
When the results are filtered by price
Then the following pets are found
| Size | Price | Type | Pet Breed |
| Small | 100 | Cat | Siamese |
| Small | 150 | Cat | Burmese |
Scenario: Searching using Min Price
Given I search using a Minimum Price of 150
When the results are filtered by price
Then the following pets are found
| Size | Price | Type | Pet Breed |
| Small | 150 | Cat | Burmese |
| Small | 200 | Cat | Siamese |
| Large | 200 | Dog | Boxer |
| Large | 250 | Dog | Sheepdog |
| Large | 500 | Primate | Chimpanzee |
| Large | 550 | Primate | Gorilla |
Scenario: Searching using Pet Type
Given I search using a type of Dog
When the results are filtered by type
Then the following pets are found
| Size | Price | Type | Pet Breed |
| Large | 200 | Dog | Boxer |
| Large | 250 | Dog | Sheepdog |
Scenario: Searching using Pet Breed
Given I search using a breed of Gorilla
When the results are filtered by breed
Then the following pets are found
| Size | Price | Type | Pet Breed |
| Large | 550 | Primate | Gorilla |
这些示例使您能够简洁地捕捉您需要考虑的所有边缘情况,而无需不必要地重复创建每个边缘情况的场景。如果随着开发的进展,您发现了更多的边缘情况,则相对容易捕获它们并确保它们得到测试。
一旦创建了场景,您可以在您选择的单元测试运行器中运行它们,SpecFlow 会将它们中的每一个标记为不确定,因为它找不到与场景匹配的任何实现代码。方便的是,SpecFlow 还为您提供了开发人员可以复制和粘贴的便捷代码片段,它为您提供了实现方法结构。SpecFlow 通过扫描它知道的程序集来工作,寻找带有 Binding
属性标记的类。一旦找到这些类,它就会寻找带有 Given
、When
或 Then
属性标记的方法,该方法有一个参数与场景的文本匹配。此语句的代码:“Given I search using a Minimum Price of 150
”可能看起来像这样
namespace Acme.RobotPets.Web.Test.Acceptance
{
using TechTalk.SpecFlow;
[Binding]
public class PetSearchSteps
{
[Given(@"I search using a Minimum Price of (.*)")]
public void GivenISearchUsingAMinimumPriceOf(int price)
{
ScenarioContext.Current.Pending();
}
}
然后您可以自由地开始编写您的实现代码,SpecFlow 框架以与执行标准单元测试代码大致相同的方式执行该代码。因此,它可以被引入到持续集成过程中,并成为一流的项目可交付成果。
查看原文.