2011-04-03 72 views
7

所以我知道,当涉及到用户故事场景时,being specificgood thing。但是,我经常会问自己:我的情景应该具体到什么程度?是否有具体的用户故事场景邪恶?

例如,对于用户的故事:

为了让项目成员合作过一个项目,作为项目经理,我希望能够注册新的项目

我们可以有以下场景:

鉴于项目从未在系统中注册过,当项目经理注册该项目时,注册的项目应该在AR在项目

或者,我们可以更具体的东西,如指定成员的名单:

鉴于斯科特是一个项目经理和从未登记在计算器一体化项目系统,当斯科特寄存器stackoverflow集成项目指定作为项目成员,然后stackoverflow一体化项目应该出现在项目

的名单我已经找到了第二届‘更具体的’一书写BDD规格时得心应手。有类似scottTheProjectManager代替projectManagerStub哪里是:

  • 更加符合现实世界(?我们没有存根担任项目经理..还是我们)
  • 更容易指每当需要(否则,我会一直说“那个项目经理”或者“项目经理谁注册了项目”......等等

我的结论是否正确?变化发生在故事上吗?

非常感谢!


更新

上面的问题不仅是有人名而不是角色名称,它是关于与实际情况的名称替换您的方案中的所有占位符。实际上,我并不是说我们实际上有一个叫斯科特的人担任项目经理,它只是给抽象占位符命名,以实现上述好处。

我会尽量展示这些优势是如何通过包括下面的代码表示使用StoryQ框架

[TestFixture] 
public class ProjectRegistrationSpecs 
{ 
    [Test] 
    public void ProjectRegistration() 
    { 
     new Story("Project Registration") 
      .InOrderTo("allow project members to collaborate over a project") 
      .AsA("project manager") 
      .IWant("to be able to register new projects") 
       .WithScenario("New Project Registration") 
        .Given(ScottIsAProjectManager) 
         .And(StackoverflowIntegrationProjectHasNeverBeenRegistered) 
        .When(ScottRegistersStackoverflowIntegrationProjectSpecifyingJaneAsAnAnalyst) 
        .Then(StackoverflowIntegrationProjectShouldAppearInJanesListOfProjects) 
     .Execute(); 
} 

//Since Scott and Jane are just instances that have meaning in the context of this user story only, they're defined private 
private ProjectManager scottTheProjectManager; 
private Project stackOverFlowIntegrationProject; 
private Employee janeTheAnalyst; 

    //Initialize the stubs in the constructor 
    public ProjectRegistrationSpecs() 
    { 
     scottTheProjectManager = new ProjectManager() 
     { 
      Id = new Guid("{A1596CFC-5FA5-4f67-AC7E-5B140F312D52}") 
     }; 

     stackOverFlowIntegrationProject = new Project() 
     { 
      Id = new Guid("{F4CD5DDE-861E-4e18-8021-730B7F47C232}"), 
      Name = "Stack Overflow Integration" 
     }; 
    } 
    private void ScottIsAProjectManager() 
    { 
     container.Get<IDataProvider>().Repository<ProjectManager>().Add(scottTheProjectManager); 
    } 
    private void StackoverflowIntegrationProjectHasNeverBeenRegisteredInTheSystem() 
    { 
     var provider = container.Get<IDataProvider>(); 
     var project = provider.Repository<Project>().SingleOrDefault(p => p.Name == stackOverFlowIntegrationProject.Name); 
     if (null != project) 
     provider.Repository<Project>().Delete(project); 
    } 
    private void ScottRegistersStackoverflowIntegrationProjectSpecifyingJaneAsAProjectMember() 
    { 
     stackOverFlowIntegrationProject.Members.Add(janeTheAnalyst); 
     scottTheProjectManager.RegisterProject(stackOverFlowIntegrationProject); 
    } 

    //instead of saying something like TheProjectThatWasAddedByTheProjectManagerShouldAppearInTheProjectMembersList, we have: 
    private void StackoverflowIntegrationProjectShouldAppearInJanesListOfProjects() 
    { 
     Assert.That(janeTheAnalyst.Projects.Any(p => p.Id == stackOverFlowIntegrationProject.Id)); 
    } 
} 

回答

2

“用户角色”一个完整的BDD风格的规范实现的是一个非常强大的,但很难掌握的概念。做得对,他们可以引导你朝着简化,优化的用户体验。如果做错了,他们会花时间给团队中的人一个主观的理由互相嚷嚷。

退房http://www.agile-ux.com/2009/12/02/personas-in-agile-development-yes-we-can/为起点。关于这个话题有大量的文献,尽管大多数不是针对BDD的。

我可以给出的最重要的一条建议是,在定义你的人物角色时,对他们感兴趣/激励/挫败他们是什么非常具体很重要,但是这种特殊性应该以整个世界或计算一般情况下 - 不要将这些东西与产品的特定方面或产品的个人愿望联系起来,因为否则1)人物角色很快就会过时,需要重新制作,以及2)这些人最终会被用作主观武器以促进你的个人愿望,而不是作为一个基于事实的工具来改进,为真实的人提供最好的产品。说起来容易做起来难。

0

当你的aproach有一个名为特定用户的海湾更容易理解该领域专家(因为 领域专家知道* Scott_the_project_manager *和他的任务),但我觉得这个形式给出违反Single_responsibility_principle:一个人可以有multible角色。

斯科特也可以参与市场营销和* Magret_the_project_manager *可能比斯科特不同的责任

1

这是到那里的角色使用的名字,因为他们更容易理解故事;他们会吸引更多灵长类动物的大脑,因为它喜欢个体而且不喜欢抽象。但是,你必须保重!尽量确保你使用的名字与你实际工作的任何人的名字不一致 - 这会让人感到非常困惑 - 并且不会对偏见进行编码 - 该项目不是偏见的事物,因为它不能有意见。也不要为不同的角色使用相同的名称;虽然现实可能与有很多角色的人混杂在一起,但用户故事不应该混淆在这种方式中,因为这只是简单的混淆。

3

您给出的第一个“场景”实际上是验收标准。它规定了适用于所有类型的项目经理,成员和指定项目的规则。

第二种情况是采用现实数据的验收标准的实例。 BDD最重要的方面是在对话中使用这样的例子,以便可以讨论故事验收标准的其他方面。

例如,考虑到stackoverflow集成项目已经被注册,当Scott试图再次注册时会发生什么?是否有任何情况下Jane的项目分配可以被拒绝?简对这个项目的分配是唯一有价值的结果吗?她会收到一封关于它的电子邮件吗?

在讨论场景时,您可能已经可以看到使用特定数据的难易程度。别忘了,:

  • 具有对话
  • 捕捉对话
  • 自动化的谈话更重要更重要。

如果你要同时做所有的三个,那么荣誉,但不要在自动化的谈话妥协。

+0

+1为完全敏捷宣言驱动的答案。 – 2011-04-24 06:51:08

+0

啊,我希望。尽管敏捷宣言,开发人员(包括我自己)很容易关注这些工具。这是多年来做错了的经验,而不是做正确的做法......我猜这也是宣言的来源。当我们没有经历过自己的学习时,我们似乎总是妥协。 – Lunivore 2011-04-24 11:05:50

1

比较从您的示例如下:

鉴于斯科特是一个项目经理和计算器一体化项目从未在系统中登记,当斯科特登记计算器集成项目指定简作为项目成员,则计算器一体化项目应该出现在项目简名单

VS:

考虑为P项目经理和未注册的项目,当项目经理注册项目并指定团队成员时,项目应出现在团队成员的项目列表中。

注意,上面的第二个例子中的写法是不是从你在你的问题给出了第一个例子太不一样了,但它是微妙的不同,以便它读取,就好像它是一个小更完整。我认为这是你可能会觉得缺失的一种方式,如果是这样的话,我会把它当作一种“故事味道”,如果是这种情况,我会不断提问并且改写直到故事/场景感觉更完整。

个人而言,我发现使用角色的注意力集中在我手头的任务上,而且我不喜欢结束于我的测试代码,而这些代码散布着不像我测试的东西那样阅读的文本。另一方面,如果您正在采用数据驱动的方法,并且为此目的定义某种数据结构,那么使用在测试范围内有意义的名称来填充该结构是有意义的。

我认为使用角色的风险之一是,他们有时最终可能会取代懒惰的方法命名,或者甚至更糟糕,因为无聊的程序员尝试在代码中注入一点幽默感。并不是说我觉得与你的名字有一点点乐趣是不好的,但如果它们不向利益相关者提供价值,那么就不应该使用它们。

另一种想法虽然发生在我身上,你可以拥有两全其美。如果您将用户角色指定为数据以提供给您的故事场景,那么您有利于保持代码清洁并符合要求,但是您可以根据实际测试执行情况使输出看起来更具体一些。例如:

new Story("Project Registration") 
     .InOrderTo("allow project members to collaborate over a project") 
     .AsA("project manager") 
     .IWant("to be able to register new projects") 
      .WithScenario("New Project Registration") 
       .Given(AProjectManager, "Scott") 
        .And(AnUnRegisteredProject, "Stack Overflow Integration") 
       .When(TheProjectManagerRegistersTheProject) 
        .And(TheProjectManagerSpecifiesATeamMember, "Jane") 
       .Then(ThenTheProjectShouldAppearInTheTeamMembersListOfProjects) 
    .Execute();