Showing posts with label Agile. Show all posts
Showing posts with label Agile. Show all posts

Wednesday, February 20, 2008

BDD and Outside-In Design

I've started using NBehave specifications to try and work out how BDD can affect the way I work.

As I touched on in my previous post. I'm hoping to try and find answers to my questions and the first one I wanted to deal with is how to best use BDD as a way of getting outside-in design.

I'm going to give an example of two approaches to using outside-in design with BDD, first though I'll explain what I'm testing:

SUT
I'm writing a Windows Service that will do the following (initially):

  1. Pick up unprocessed messages describing events related to domain classes.
  2. Go through each message in turn.
  3. Take the message and convert it to an XML document
  4. Send the XML message to our integration platform (BizTalk).
  5. Mark the original message as processed.
  6. Look for steps 3-5 until done.
This is a very much a technical piece of work but I don't see why BDD can't be used for such a task.

Story Definition
I'll define this overall story in NBehave syntax as:

story
.AsA("...")
.IWant("all domain event messages to be processed")
.SoThat("we send them to the integration platform");
Simple Test
To get going I want to start with a single simple test:

  1. Load the single unprocessed domain event message
  2. Create the XmlDocument describing the event and domain object.
  3. Send the XmlDocument.
Mock Style
The first way I think you can use BDD for high-level testing is something like the approach from Mock Roles, Not Objects:


[Test]
public void We_process_change_X_to_Y()
{
DomainEventMessage message = CreateMessageForAccountActivation();
_testMessages.Add(message);

#region Setup Expectations

XmlDocument emptyDocument = new XmlDocument();

Mock mockMapper = MockManager.Mock(typeof(AccountEventMessageMapper));
mockMapper.ExpectAndReturn("ConvertToXmlMessage", emptyDocument).Args(message);

Mock mockMapperFactory = MockManager.Mock(typeof(DomainEventMessageMapperFactory));
mockMapperFactory.ExpectAndReturn("GetMapper", new AccountEventMessageMapper()).Args(message);

Mock mockMessageSender = MockManager.Mock(typeof(XmlMessageSender));
mockMessageSender.ExpectCall("Send").Args(emptyDocument);

#endregion

story
.WithScenario("processing single event message")
.Given("there is a single unprocessed message relating to an X", MockRepositoryToReturnMessages)
.When("we process the event messages", ProcessMessages)
.Then("an appropriate Xml message is sent", VerifyExpectedCallsWereMade);
}
Its worth noting here that I'm using TypeMock (and only features from the free community edition) and not injecting in the dependencies so I'm not strictly sticking to the approach that the mockobjects guys push for. Having said that I am thinking that this is certainly a situation where I will be bringing in DI/IoC.

So what do I think of it? I guess this test is useful, it definitely made me think about the collaborators. To get the test to pass I have to put the followinge code into the SUT:

IList unprocessedMessages = new DomainEventMessageRepository().GetAll();

AccountEventMessageMapper mapper = DomainEventMessageMapperFactory.GetMapper(unprocessedMessages[0]);

XmlDocument xmlDocument = mapper.ConvertToXmlMessage(unprocessedMessages[0]);

new XmlMessageSender().Send(xmlDocument);
This seems like a good initial design (ignoring names of classes/members and possibility of DI). Having said that I'm not convinced that I wouldn't have come up with a design as good or better if I'd just relied on normal state based testing. Mind you at least with this approach I have come up with a list of requried collaborators early which is useful.

Now down to a problem though, although this test now passes my SUT does nothing because the collaborators all have do nothing implementations. This means that we're out of luck if we're expecting this specification to act as our acceptance criteria.

State Testing
Lets look at what I might do for a state based test:

[Test]
public void We_process_change_X_to_Y()
{
story
.WithScenario("processing single event message")
.Given("there is a single unprocessed message relating to an X", CreateAndSaveMessage)
.When("we process the event messages", ProcessMessages)
.Then("an appropriate Xml message is sent", AssertCorrectXmlDocumentProduced);
}
In this case the methods being called would probably be real implementations or at worst would use test stubs/spies. So I'd be thinking that CreateAndSaveMessage would create a real DomainEventMessage and would save it to the database.

So how do I get this test to pass, the truth is it will take me a while. I'll need to implement all the collaborators fully enough to handle this simple case (single message being processed) and I need to define the expected XML document before starting the work.

The good bit is that once I'll know that the system is handling the one simple case, which makes it a useful acceptance test.

Summary
I actually think that for the problem at hand both tests are good.

I don't rate the way most people use mocks, it often just ends up in unreadable over-coupled tests that are difficult to follow. However in this case we're showing high level collaborations that are indeed meaningful. I question the value of always thinking about all of the collaborators upfront but in this case it could be useful.

How do I apply both types of tests though, the options I'm going to try are:

  1. Write Both - Since I'm not sure I need that many tests that show the collaborations this could work.
  2. Write Mock Ones And As I Implement Remove The Mocks - I'd write a mocking test and as I write the real collaborators I'll go back and replace the mock implementation with the real one. Once there is no mocking in the test I'm done.
  3. Avoid Mocking - This is the approach discussed in this NBehave thread.

Initially I might go for the first approach, writing a few mock/behavior style tests but mainly writing state ones.

Share This - Digg It Save to del.icio.us Stumble It! Kick It DZone

Tuesday, February 05, 2008

Team System and Agile - Do they go together?

I blogged about this a while ago but we've been trying introduce a user story based requirement process, our user stories would be stored in TFS and the users would access them using the Web Access Power Tool (previously called TeamPlain).

Sounds good, especially as the tool is free. Problem is every single user who wants to use the web portal to access TFS is going to have to have a CAL. I've complained about this before, and even logged a bug with Microsoft about it, but really it doesn't seem like they understand how big a problem this is.

Given the situation I would truly question whether any company should consider using Team System unless they are also prepared to hand over large sums of money to get their users involved. If you decide not to use TFS for artifacts such as user stories then its really just an expensive source control system.

Share This - Digg It Save to del.icio.us Stumble It! Kick It DZone

Scrummerfall

Jimmy Bogard, who is becoming one of my favorite bloggers, has two excellent posts on Scrummerfall here and here. If you are "doing agile" but finding its only really changing the development team then they may be relevant.

To be honest we don't do Scrummerfall, we didn't start out with Scrum.

Share This - Digg It Save to del.icio.us Stumble It! Kick It DZone

Friday, March 30, 2007

Team System And Agile

Having used Team System for about a year now I've come to quite like it, bits of it could be improved but as a developer it is quite a nice environment to work in.

However there is a serious problem with its usage within an agile team, the problem being the outrageous cost of getting users involved.

For example we want to get our users involved early on in the requirements process and to do this we're planning to use a user story based approach. Personally I think it'll work far better than the requirements document or use case approaches that I've used in the past.

Anyway to make this process work we need a way to get our users involved and since they are at the other end of the country from us we have to look at combining software with regular phone calls.

With this in mind I've used the Process Editor bit of the Team Foundation Power Tool to create a custom user story work item and we're getting our users to trial TeamPlain so that they can see/modify the actual work items.

The idea is that they specify the work item and that it will then move through multiple states. It will start in a new state, once the users have specified acceptance tests they can move it to a signed off state, we in the development team will than handle moving it to the in progress and complete states and finally when the users get the release they can use the acceptance tests to test the functionality before moving it to a closed state (if all goes well).

I think this should work fine and, despite a few issues, TeamPlain likes a good tool for our users to play with.

The only problem, and its a huge one, is that in order for our users to interact with Team System in the way we want them to each of them will need a client access license. This will add massively to the cost of team system and goes against the aims of agile to a point that seems ridiculous.

Share This - Digg It Save to del.icio.us Stumble It! Kick It DZone