したがって、ユーザーストーリーのシナリオに関しては、具体的にすることは良いことです。しかし、私は頻繁に自分自身に問いかけることになります。私のシナリオはどの程度具体的である必要がありますか?
たとえば、ユーザーストーリーの場合:
プロジェクトメンバーがプロジェクトで共同作業できるようにするために、プロジェクトマネージャーとして、新しいプロジェクトを登録できるようにしたいと思います。
次のシナリオが考えられます。
プロジェクトがシステムに登録されたことがない場合、プロジェクトマネージャーがそのプロジェクトを登録すると、登録されたプロジェクトが指定されたメンバーのプロジェクトリストに表示されます。
または、次のように具体的にすることもできます。
スコットがプロジェクトマネージャーであり、スタックオーバーフロー統合プロジェクトがシステムに登録されたことがない場合、スコットがジェーンをプロジェクトメンバーとして指定してスタックオーバーフロー統合プロジェクトを登録すると、スタックオーバーフロー統合プロジェクトがジェーンのプロジェクトリストに表示されます。
2番目の「より具体的な」ものはBDD仕様を書くときに便利だと思いました。projectManagerStubの代わりにscottTheProjectManagerのようなものがある場合:
- より現実の世界に合わせて調整します(プロジェクトマネージャーとして機能するスタブはありません。それとも私たちですか?)
- その仕様のコンテキストで必要なときにいつでも参照しやすくなります(それ以外の場合は、「そのプロジェクトマネージャー」または「プロジェクトを登録したプロジェクトマネージャー」などと言い続けます。
私は私の結論に正しいですか?ストーリーに変更が生じた場合、その特異性は私に害を及ぼしますか?
どうもありがとう!
アップデート
上記の質問は、役割名の代わりに個人名を使用することだけでなく、シナリオ内のすべてのプレースホルダーを実際のインスタンスの名前に置き換えることでもあります。実際には、Scottという人がプロジェクトマネージャーとして働いているという意味ではありません。前述の利点を実現するために、抽象的なプレースホルダーに名前を付けているだけです。
StoryQフレームワークを使用して完全なBDDスタイルの仕様を表す次のコードを含めることにより、これらの利点がどのように実現されるかを示します。
[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));
}
}