Tuesday, January 18, 2011

A story about User Stories; What are they and why do you need them?

In this multi-part post, I’m going to share my personal experiences while working with user stories for gathering, tracking and planning requirements.
You can also download all parts as one comprehensive PDF for easy printing or e-reading.

What’s a user story?
So let me start with a definition. The ideal user story represents an independent, estimable and prioritizable functional or non-functional requirement, is written in the language of the business and adds value to the project or system. That’s it? Well no, it’s not that easy unfortunately, but I promise you will get a whole lot closer after reading this article (or run away screaming with more questions than you started with).

Why should I read it?
With the introduction of Team Foundation Server 2010, Microsoft showed that they are finally embracing the best practices of Scrum and Extreme Programming. The MSF Agile 5.0 process template contains a dedicated User Story work item type and includes reports and Excel workbooks that keeps you in control of your entire development process. If you ask me, that’s a great opportunity for delving deep into the depths of an Agile user story.

image

Is it a Use Case?
You might think that a UML use case or a task from a more traditional work-breakdown also meets the above definition. But nothing could be further from the truth. Alistair Cockburn, an authority on UML and the Rational Unified Process (RUP), has documented five levels at which use cases can be scoped. For instance, RUP usually involves writing use cases at sea level that describe (a part of) a business process which, by definition, covers a large part of a system. Ordina and Cap Gemini often work with use cases at fish level where a use case typically represents a screen or a part of it. Sea level use cases have the disadvantage that they are too large to use as a planning unit, while fish level use cases can provide only part of the desired functionality. I have a lot of experience with fish level use cases, and although they are very useful for obtaining a rough size estimate in Use Case Points (a method coined by Gustav Karner), they are often still too large to serve as a unit of work in an Agile project.

Then, what is it?
I think that one of the essential differences between stories and other requirements management techniques is the way in which large chunks of functionality are broken down into small bite-sized and estimable pieces. Imagine for example that you want to introduce the concept of a product to an E-commerce website. In many projects, building this may require breaking it down in a number of tasks or use cases. The administrator might need a screen for managing products, whereas the potential buyer might need a screen for searching for products based on certain criteria.

Every project has to prioritize its work. In a use case-oriented project it is quite possible that the screen for searching is built much later than the management screen. And because the team realizes use case by use case, and consequently, screen by screen, chances are that the team will first finish the management screen including all the bells and whistles requested by the client. The big downside is that the desired functionality is not finished until both screens have been fully built. In an Agile project it is quite possible that due to changes in priority or scope the 2nd screen is never build.

User stories try to deal with that by requiring that the above mentioned functionality only has business value if the entire process of product managing and searching works. Obviously you run the risk that this results in a big chunk work that is difficult to plan or tack. That’s why you need to explicitly distinct between the core functionality needed to allow the end-user to accomplish his task, and all the extras that make it easier to use.

For instance, the first story might only involve a simple entry form without any UI-specific considerations, validation or a fancy selection list, and a screen with a list of products from which the buyer can select one. Adapting the layout to the corporate standards, the ability to categorize products, and advanced validation should all be realized as separate user stories. And yes, I know, those stories wouldn’t be completely independent from the original story. But at least they force you to focus on the core functionality. After finishing the first story, the user will gain a better sense of the system being build and may be better able to provide feedback. In fact, in many projects the first story becomes a catalyst for new ideas and insights.

Is it the functional design?
It’s not. A study performed by the Standish Group involving more than 40,000 projects revealed several common reasons for the failure of so many projects. One of those reasons was that projects erroneously assume that it is possible to write down functional requirements in an unambiguous way.
Another one involved the equally wrong assumption that the business knows exactly what they want from the start. Hence Agile methodologies work with short cycles and strongly favor intensive involvement of the business.

That is exactly why a user story should be seen as a reminder to have a more detailed discussion with the business stakeholder at the time the functionality is going to be built. Only then you’ll be able to gain the most from the increasing insights of executing a project. And only then it is possible for the stakeholders to evaluate a live version of the system, albeit in an early stage. Watching an early version of a product is often a catalyst for a lot of new requests or changes to the requirements

But stories are finite so they cannot be used as lasting functional documentation. In other words, while the product or system is still under construction, the stories are used as a placeholder for notes, discussions, estimations and to keep progress. But when the functionality has been realized, the stories won’t have enough details to be used as a future reference. Worse, the stories are usually not even updated if improvements and additions are made during a demo to the stakeholder.

Additionally, while executing our first project using stories, we noticed that we lacked some structure. First, the team needed a central place to store the concepts and business rules from the business domain. Because I already had a lot of experience with domain models such as defined by Martin Fowler, and I got more and more involved in the principles of Domain Driven Design (a concept introduced by Eric Evans), it was obvious to me that we were going to use a domain model here.

Also, the customer representative sometimes lots the overview of the many stories that were on our list of requirements. After a bit of Googling, I ran into a whole series of posts and discussions initiated by Alistair Cockburn. Alistair had the same problems and experimented with use case diagrams to illustrate the system context. I now use use cases diagrams to represent the screens, external dependencies and processes. This appeared to be very helpful while talking to your customers about a new feature. And even though you can store the entire functional design in a use case, we stick to simple diagrams only. All functional details are still stored in the stories.

Who? What? Why?
To conclude this first part, a final aspect of user stories is the fact that traditional requirement gathering techniques usually deal with the needs or desires of the stakeholders, and if you’re lucky, with the roles a user needs to have for that. However, these techniques almost always lack the reason behind such a requirement or identify the goals the user tries to reach. Consequently, user stories must be written in the form "As who, I want what, so that I why. The who describes the role or the stakeholder in whose interest the requirement defined by the what was introduced. The why should explain why the requirement is so important for the product, the project or the stakeholder. A nice example of how that can help us as developers is that because we now know what the stakeholders tries to accomplish, we might be able to come up with a better alternative. Be aware though that you don’t end up with a reason that practically repeats the what. The trick is to keep on asking until you find the real reason.

Next time I’ll be discussing some tips and advices on how to gather and write them as well as how to control their scope.

Saturday, January 15, 2011

Fluent Assertions as a NuGet package

As of now you can download the latest version of Fluent Assertions directly from within Visual Studio 2010. Just install the NuGet package manager, select Add Library Package Reference from the project context menu and search for FluentAssertions.

image

Tuesday, January 04, 2011

Verifying PropertyChanged events in Silverlight using Fluent Assertions

Yesterday, I blogged about the newest release of Fluent Assertions for .NET and Silverlight and promised to demonstrate the new event monitoring syntax. Since I’m a Silverlight addict, I decided to show you an example of a MVVM unit test when using the traditional Assert class and the same example using Fluent Assertions.

Let’s start with the traditional example first. Notice the BDD-style I’m using here. If you want to learn more about it, check out my previous post on unit testing in Silverlight.

[TestClass]
public class When_activating : SpecificationContext
{
   
private FindActivitiesViewModel model
;
   
private IEnumerable<Product> products
;
   
private IEnumerable<Country> countries
;
   
private readonly List<string> changedProperties = new List<string
>();

   
protected override void EstablishContext
()
    {
       
model = new FindActivitiesViewModel
();

       
model.PropertyChanged += (sender, args) =>
changedProperties.Add(args.PropertyName
);

       
products = new
[]
        {
           
new ProductBuilder().Named("Trucks").Build
(),
           
new ProductBuilder().Named("Cars").Build
()
        };

       
countries = new
[]
        {
           
new CountryBuilder().Named("Netherlands").Build
(),
           
new CountryBuilder().Named("Belgium").Build
(),
           
new CountryBuilder().Named("Luxemburg").Build
()
        };
    }

   
protected override void Because
()
    {
       
model.OnActivate
();
    }

    [
TestMethod
]
   
public void It_should_expose_all_countries_sorted_by_name
()
    {
       
CollectionAssert.AreEqual(
countries.OrderBy(c => c.Name).ToArray(), model.Countries.ToArray());
       
CollectionAssert.Contains(changedProperties, "Countries"
);
    }

    [
TestMethod
]
   
public void It_should_expose_all_products_sorted_by_name
()
    {
       
CollectionAssert.AreEqual(
products.OrderBy(p => p.Name).ToArray(), model.Products.ToArray());
       
CollectionAssert.Contains(changedProperties, "Products"
);
    }

    [
TestMethod
]
   
public void It_should_not_expose_search_results_yet
()
    {
       
Assert.AreEqual(0, model.FoundActivities.Count
());
    }

    [
TestMethod
]
   
public void It_should_not_have_an_initial_selection
()
    {
       
Assert.IsNull(model.SelectedCountry
);
       
Assert.IsNull(model.SelectedProduct
);
    }

    [
TestMethod
]
   
public void It_should_not_be_possible_to_search
()
    {
       
Assert.IsFalse(model.CanSearch
);
    }
}

Pay some attention to the way I’m verifying that the property changed events were raised, and note the superfluous usage of ToArray() when comparing collections. Why on earth did MS decide to have CollectionAssert.AreEqual() take an ICollection instead of an IEnumerable?


Anyway, let’s see the equivalent example using Fluent Assertions.

[TestClass]
public class When_activating : SpecificationContext
{
   
private FindActivitiesViewModel model
;
   
private IEnumerable<Product> products
;
   
private IEnumerable<Country> countries
;
   
   
protected override void EstablishContext
()
    {
       
model = new FindActivitiesViewModel
();
       
model.MonitorEvents
();

       
products = new
[]
        {
           
new ProductBuilder().Named("Trucks").Build
(),
           
new ProductBuilder().Named("Cars").Build
()        };

       
countries = new
[]
        {
           
new CountryBuilder().Named("Netherlands").Build
(),
           
new CountryBuilder().Named("Belgium").Build
(),
           
new CountryBuilder().Named("Luxemburg").Build
()
        };
    }

   
protected override void Because
()
    {
       
model.OnActivate
();
    }

    [
TestMethod
]
   
public void It_should_expose_all_countries_sorted_by_name
()
    {
       
model.Countries.Should().Equal(countries.OrderBy(c => c.Name
));
       
model.ShouldRaisePropertyChangeFor(m => m.Countries
);
    }

    [
TestMethod
]
   
public void It_should_expose_all_products_sorted_by_name
()
    {
       
model.Products.Should().Equal(products.OrderBy(p => p.Name
));
       
model.ShouldRaisePropertyChangeFor(m => m.Products
);
    }

    [
TestMethod
]
   
public void It_should_not_expose_search_results_yet
()
    {
       
model.FoundActivities.Should().BeEmpty
();
    }

    [
TestMethod
]
   
public void It_should_not_have_an_initial_selection
()
    {
       
model.SelectedCountry.Should().BeNull
();
       
model.SelectedProduct.Should().BeNull
();
    }

    [
TestMethod
]
   
public void It_should_not_be_possible_to_search
()
    {
       
model.CanSearch.Should().BeFalse
();
    }
}
The difference may not be mind blowing. But if you care for intention revealing unit tests as much as I do, you should seriously consider checking out the documentation for the exception throwing and the property comparison assertion extensions.

Monday, January 03, 2011

A new year with a new release of Fluent Assertions

Christmas usually means a week off and a whole lot of free time between the social obligations and spending some quality time with my wife and daughter. That’s why I decided to get rid of some of the backlog items for the next version of Fluent Assertions. And I’m done, version 1.3.0 is a fact.

New Features
  • Introduced a new set of extension methods for asserting that events were raised with the appropriate data. With his permission, I borrowed, adapted and integrated the code from Mendelt Siebenga’s original EMo project. I’ll write up a separate post on how to use this in Silverlight testing.
  • BeOfType<T>() and BeAssignableTo<T>() are available for all reference types. Before this, they were only available on the ObjectAssertions class.
  • Added an OnlyContain() method to the collection assertions that takes a lambda expression and ensures that the collection only contains items matching the predicate.
  • Added an overload of Contain() to the collection assertions that takes both an IEnumerable<T> and a params array. I regularly ran into the situation that I wanted to check if a particular new item was added to a collection. With this overload, you no longer need to create a temporary list that contains both the original collection and the newly added items.
  • Added support for ShouldHave().SharedProperties().EqualTo(otherObject). This saved me a lot of work when asserting that some DTO-entity conversion was implemented correctly. Before I had to exclude all the properties that I didn’t want to include in the DTO, or swap the calling order, neither improving the readability. But since you still may end up wanting to exclude a particular property, I also added an additional But(x => x.Property) method that can be combined with AllProperties() and SharedProperties().

Breaking Changes
  • Changed the way test framework assemblies are found so that they are not relying on specific versions anymore. In fact, I introduced separate versions for .NET 3.5 and .NET 4.0 that both support all test frameworks. They will automatically find the test framework assembly, but you can force it using an <appSetting>.
  • Switched to Silverlight 4 for the Silverlight version of Fluent Assertions.
  • Renamed the Assertions base-class to ReferenceTypeAssertions because it better explains its purpose.
  • BeOfType<T>() was not properly checking that the subject was of the exact same type rather than a subclass. I fixed this, but it may break existing unit tests.

Improvements/Bugs
  • Signed all assemblies with a strong name.
  • Added some missing XML comments.
  • Improved the extensibility by exposing the subject-under-test via a public Subject property and making all contructors protected.
  • If the exception message is shorter than the expected one specified using WithMessage(), but starts with the same text, it was not detected as a difference.
  • Fixed a NullReferenceException when calling ObjectAssertions().Be() on a null object.
  • As<T>() uses a type safe-cast now so that you can do stuff like someObject.As<SomeType>().ShouldNotBeNull();
  • Fixed a bug that caused the property comparison assertions to ignore internal or base-class properties.
I’ve also updated the documentation to include these changes and completed it with some missing information on the property comparison features that I introduced in version 1.2.0.