Mark Needham

Thoughts on Software Development

Archive for the ‘Testing’ Category

TDD: Testing sub classes

with 11 comments

We ran into another interesting testing dilemma while refactoring the view model code which I described in an earlier post to the point where we have an abstract class and three sub classes which means that we now have 3 classes which did the same thing 80% of the time.

As I mentioned in a post a couple of weeks ago one of the main refactorings that we did was to move some calls to dependency methods from the constructor and into properties so that those calls would only be made if necessary.

After we’d done this the code looked a bit like this:

public abstract class ParentModel
{
	private readonly Dependency1 dependency1;
 
	...
 
	public decimal Field1 { get { return dependency1.Calculation1(); } }
	public decimal Field2 { get { return dependency1.Calculation2(); } }
}
 
public class BusinessProcess1Model : ParentModel { }
public class BusinessProcess2Model : ParentModel { }
public class BusinessProcess3Model : ParentModel { }

We wanted to ensure that the tests we had around this code made sure that the correct calls were made to ‘depedency1′ but because ParentModel is an abstract class the only way that we can do this is by testing one of its sub classes.

The question is should we test this behaviour in each of the sub classes and therefore effectively test the same thing three times or do we just test it via one of the sub classes and assume that’s enough?

Neither of the options seems really great although if we cared only about behaviour then we would test each of the sub classes independently and forget that the abstract class even exists for testing purposes.

While the logic behind this argument is quite solid we would end up breaking 3 tests if we needed to refactor our code to call another method on that dependency for example.

I suppose that makes sense in a way since we have actually changed the behaviour of all those classes but it seems to me that we only really need to know from one failing test that we’ve broken something and anything beyond that is a bit wasteful.

In C# it’s not actually possible for ‘Field1′ or ‘Field2′ to be overriden with an alternate implementation unless we defined those properties as ‘virtual’ on the ‘ParentModel’ which we haven’t done.

We could however use the ‘new’ keyword to redefine what those properties do if the callee had a reference directly to the sub class instead of to the abstract class which means it is possible for a call to ‘Field1′ to not call ‘dependency1′ which means that maybe we do need to test each of them individually.

I’m not sure which approach I prefer, neither seems better than the other in my mind.

Written by Mark Needham

September 13th, 2009 at 10:21 pm

Posted in Testing

Tagged with

TDD: Test only constructors

with 11 comments

I wrote previously how we’d been doing some work to change the way that we get a ‘User’ object into our system and one mistake that we made intially was to have another constructor on the ‘User’ object which was being used in all our unit tests which involved the user in some way.

The original reason that this ‘test constructor’ was created was to make it easier to construct a ‘fake user’ which we were using in some of our functional tests but had ended up being used in unit tests as well.

The constructor being exposed for testing was pretty much the same as the private constructor that we have now.

public class User
{
	...
	public User(string userName, string customerId)
	{
		this.userName = userName;
		this.customerId = customerId;
	}
}

The problem with this approach to testing is that we aren’t actually testing the code which we’re using in production so even if the tests pass it doesn’t actually tell us very much about our code.

We could be doing everything right in this test constructor and doing something crazy in the static factory method and we wouldn’t find out until much later on.

The interesting thing is that the method that we call from the production code isn’t as testing friendly as the one we had made public just for testing:

	public static User CreateUserFrom(NameValueCollection headers)
	{
		var userName = headers["user-name-header-tag"];
		var customerId = headers["customer-id-header-tag"];
 
		// and so on
 
		return new User(userName, customerId);
	}

In order to make our test setup code use this method we had to create a NameValueCollection containing key/value pairs with the appropriate keys that reside in the headers of requests coming into our application.

We therefore end up with code similar to this in the test data builder:

public class UserBuilder
{
	...
 
	public User Build()
	{
		var headers = new NameValueCollection();
		headers.Add("user-name-header-tag", "randomName");
		headers.Add("customer-id-header-tag", "customerId");
		User.CreateUserFor(headers);
	}
}

This leaks a bit of the implementation of ‘CreateUserFrom’ into the tests but I prefer this to testing something which is never actually used.

Written by Mark Needham

September 12th, 2009 at 12:35 am

Posted in Testing

Tagged with

Impersonators: Using them in showcases

with one comment

Towards the end of my colleague Julio Maia’s blog post about the impersonator pattern he suggests that the standalone environment that we can create through the use of impersonators can be quite useful for showcases and we actually had a recent occasion where we had to switch mid-showcase from using the integration environment to make use of an impersonator.

In this case part of the environment went down in the middle of the showcase so if we wanted to keep on going then that was our only option but in general the expectation of the business is that our showcases show them the functionality of the application end to end.

We need to be careful when using a standalone environment that the business are aware of this because it’s quite likely that the application is going to respond much more quickly than it would if it was fully integrated.

If people aren’t aware of this then they will be very surprised when the application isn’t quite as performant when we put it into a real environment and it has to retrieve and store real data instead of just getting pre-stored values from an in memory impersonator.

Another disadvantage of using a standalone environment is that we must ensure that we only enter data which we have previously entered otherwise we’ll either go against the real environment if we’re using a self initializing fake or (I think) just get no response if we’re using a record/replay type impersonator.

If we’re letting a business user drive the application during a showcase then we’ll need to ensure that they know which data they can enter.

As long as we’re careful in those regards I think it can be quite a useful approach since we can make our showcase independent of factors that our outside of our control – for example in our most recent showcase we had to reschedule the time because one part of the server was going to be restarted at our initial showcase time.

I definitely like the idea of using the impersonator for the safety it brings although my thinking at the moment is that maybe it’s best to use it as a backup option if the real environments aren’t working.

I’d be interested to hear if others have experiences around this area.

Written by Mark Needham

September 10th, 2009 at 12:23 am

Posted in Testing

Tagged with ,

TDD: Test the behaviour rather than implementation

with 4 comments

I previously wrote about some duplicated code we’d taken the time to remove from our code base and one something else that we found when working with this code is that a lot of the tests around this code were testing the implementation/internal state of the object rather than testing the behaviour that they expected to see.

I find it makes more sense to test the behaviour since this is the way that the object will most likely be used in our production code.

For example, in the code I posted previously we were setting up the way that a navigation bar was going to behave in different scenarios.

This was one of the tests we had:

public void ShouldSetLogin()
{
	var navigationModel = new NavigationModel(Options.Login);
	Assert.IsTrue(navigationModel.IsConfiguredWith(Options.Login));
}

For this (cut down for example purposes) code:

public enum Options 
{
	Login = 1,
	Logout = 2
	// and so on
}
public class NavigationModel
{
	public NavigationModel(Options options)
	{
		Configuration = options;
	}
 
	public Options Configuration { get; private set; }
 
 
	public bool IsConfiguredWith( Options expectations)
	{
		return expectations == Configuration & expectations);
	}
 
	public bool ShowLogin() 
	{
		return IsConfiguredWith(Options.Login);
	}
}

There were 7 different types of options as I mentioned in the previous post and the NavigationModel was being setup with each of them and the ‘IsConfiguredWith’ method was then being called to check whether the value had been set.

The strange thing was that everything we wanted to test could be done by calling methods like ‘ShowLogin’ which made us of the ‘IsConfiguredWith’ method anyway.

The first refactoring was therefore to change the tests to make use of these methods instead of calling on an implementation detail of the NavigationModel:

public void ShouldShowLogin()
{
	var navigationModel = new NavigationModel(Options.Login);
	Assert.IsTrue(navigationModel.ShowLogin());
}

There’s not really that much difference in what the test does in this case but by changing all the tests to make calls to the methods that we use in our production code we were able to make the ‘IsConfiguredWith’ method private which is quite nice since it was only being used inside the tests and the ‘Show…’ methods so it didn’t really make sense to have them public.

The next step after this was to create the factory methods that I mentioned in the previous post and since each of these methods encapsulated more behaviour the tests started to look a bit better:

public void ShouldShowLoginAndOption1AndOption2ForAnonymousUser()
{
	var NavigationModel = NavigationModel.ForAnonymousUser();
 
	Assert.IsTrue(navigationModel.ShowLogin());
	Assert.IsTrue(navigationModel.ShowOption1());
	// and so on
}

This is quite a simple example but I found it interesting that with just a little bit of tweaking we could change our tests to execute the same methods that will be run in production and combined with the other refactoring we can now encapsulate the way we are determining whether a user can see a certain option or not and potentially change the implementation of that in the future if we want to.

Written by Mark Needham

September 2nd, 2009 at 12:42 am

Posted in Testing

Tagged with

Rock Scissors Paper: TDD as if you meant it

with 4 comments

I decided to spend a bit of time on Saturday having another go at writing Rock Scissors Paper while following Keith Braithwaite’s TDD as if you meant it exercise.

We previously did this exercise at a coding dojo but I wanted to see what happens when you code for a longer period of time with this exercise since we typically only code for maybe a couple of hours at a dojo.

I decided to also checkin the code I was writing into Git after every single change I made – an idea I originally learnt from Dan North, and the code is all on github.

What did I learn?

  • I was coding for maybe 4 or 5 hours and checked in about 120 times which is far more frequently than I would do normally although perhaps it shouldn’t be.

    I thought it would be quite distracting to have to check in that often but the checkin messages ended up becoming a stream of consciousness of what I was thinking which proved quite useful on a few occasions when I got side tracked a bit and retraced my steps in the history to find out what I was supposed to be doing – Git was pretty much acting as my sounding board since I didn’t have a pair to work with on this exercise.

    I’d definitely try this out again and as I’ve mentioned a few times I want to try it out in a coding dojo some time.

  • While trying to remove some duplication that had worked its way into the code I realised that the template method would be the easiest way to remove that duplication and as I mentioned in an earlier post, having functions/actions in C# makes the implementation of this pattern a bit simpler:
        public abstract class ThrowBase : IThrow
        {
            private readonly Func<IThrow, bool> beatenBy;
     
            protected ThrowBase(Func<IThrow, bool> beatenBy)
            {
                this.beatenBy = beatenBy;
            }
     
    	 ....		
     
            public bool Beats(IThrow aThrow)
            {
                return IsDifferentThrowTo(aThrow) && !beatenBy(aThrow);
            }
     
        }
    }
        public class Scissors : ThrowBase
        {
            public Scissors() : base(weapon => weapon.BeatsScissors()) { }
     
    	...
        }

    If we didn’t have functions then we’d need a method on ‘ThrowBase’ which we would need to implement in each of its sub classes.

    As it is we can just pass a function into the constructor which does the same job.

  • Another thing I found quite interesting about this exercise was that I was seeing more easily where methods didn’t seem to belong on an existing object and I ended up creating a new object which described the interaction – chatting about the code with Liz she pointed out that I was probably creating domain events which we had discussed a few days earlier in book club.

    Once I started thinking about this interactions as ‘domain events’ the naming of them seemed to be much more obvious – for example after this conversation with Liz I realised that the interaction between two ‘Throws’ would be a ‘ThrowDown’ and that there would probably be a ‘ThrowDownAdjudicator’ to decide the outcome of a ‘ThrowDown’.

  • I found it quite difficult to follow the rules of the exercise when I realised that I wanted to return a ‘ThrowDownResult’ which would indicate whether there was a winner for a ‘ThrowDown’ and if so who it was. I couldn’t see a way to write all of this code in the test since I had already created the class previously so I ended up writing this code straight onto the class.

    I think I probably extracted to a class too early on some occasions instead of waiting for a more complete version of a method to be written before moving it.

    Next time I think I’d wait until I’d completed all the examples /tests I want to write around a particular method before moving it onto a class.

Written by Mark Needham

August 24th, 2009 at 10:11 pm

Posted in Testing

Tagged with

TDD: Asserting on test dependency code

with 3 comments

Something I’ve noticed a bit lately is tests which setup a load of dependencies for a test and then do assertions on that setup before getting on to calling the system under test.

The code tends to be similar to this:

public void ShouldHopefullyDoSomeAwesomeStuff()
{
	// setup via expectations for dependency1 and dependency2
	Assert.IsNotNull(dependency1.DependedOnMethod);	
 
	new SystemUnderTest(dependency1, dependency2).DoThatStuff();
 
	// test assertions
}

I’ve done this a fair few times myself and I used to believe that it actually made the test more valuable since we were ensuring that the dependencies were in a good state before we executed the test.

Looking at those types of assertions nowadays it feels like waste to me because we are basically testing our ability to setup the test correctly which is not the point of writing the test.

In addition tests written like this are more noisy and difficult to read for me at least as I find my eye is drawn to the assertions (and therefore typically to the end of the test) so having more than one block of these is a bit confusing.

If we’re not sure that we’ve set up the dependency correctly then an alternative is to try and simplify the setup of that dependency so that it’s really obvious that we’ve done it right.

There are a couple of ways that I’ve come across for doing this:

  • Ensure that all the setup for the test is done inside the test and not in setup methods.
  • Extract away test data setup that we don’t care about by making use of test data builders where possible.

I’ve previously suggested that I found it quite useful to extract methods for groups/individual expectations/stub calls but I think this may have inadvertently led to the above pattern since the code that we care about is now hidden a click away from where we need it.

I think I’d probably take the hit of having some duplication in tests instead of making the test more difficult to understand although like with all things there’s definitely a trade off to make.

Written by Mark Needham

August 19th, 2009 at 11:19 pm

Posted in Testing

Tagged with

Impersonators: Finding the enabling point

without comments

One of the other interesting problems that we’ve come across while making use of different impersonators in our build process, and which Julio mentions at the end of his comment on Gil Zilberfeld’s blog post, is trying to work out where the correct place for the impersonator is.

Ideally we want to put the impersonator in a place where we can easily turn it on or off depending on whether we want to use the impersonator or the real end point. In fact if we aren’t able to do this then it is perhaps the case that we haven’t actually created an impersonator at all.

I like to use the term ‘enabling point‘, which I learnt from Michael Feathers in his chapter on seams in Working Effectively With Legacy Code, to describe the place where we can make the decision to use the impersonator or the real end point.

Ideally this will probably be determined by changing a simple setting in a configuration file.

If you choose the wrong enabling point the ‘impersonator’ may not actually help you that much and it might even become such a hindrance that you stop using it and just accept the problems we can have when we have to integrate against real end points all the way through our build process.

On the way to making use of the self initializing fake on my current project we tried/thought about some other approaches which we thought might be able to ease the pain of integrating directly against the service layer which were quite unstable at the time.

We were often losing 4 or 5 hours a day due to the website being unusable without this integration point working.

Stubs

The first thought was that perhaps we could just integrate against a stub of each of the services in our development environment and then inject either the stub or real service into our code through dependency injection.

Julio points out quite an important flaw with this approach:

It happens that the results of those tests have very limited value, as they’re not actually validating if the system actually integrates correctly with its environment.

If there was a change to the structure of the xml being returned we wouldn’t know about this until we actually ran a test against the real integration point and our feedback cycle is now fairly slow.

In addition we would be returning a canned set of results from data that we had setup and the maintenance of this canned data just becomes a real pain after a while.

The internal cache

The first approach that we tried involved intercepting the requests/responses of each of the service calls from inside the application itself by making use of interceptors injected from our DI container around the classes which made the calls.

We eventually managed to get this working to a stage where we could save the requests and responses to disk and then make use of this data when the services weren’t working.

The problem with this approach was that we were configuring it by configuring a ‘UseCache’ property in our configuration file which I think was probably a sign that we were doing something wrong, the problem being that we made use of the ‘UseCache’ property in our production code.

We only setup the recording part of the process to record the requests and responses from our service tests when run as part of the build and then saved those results onto a remote server.

Another step we needed to do to make use of the ‘impersonator’ was therefore to copy those files across to the local machine and put them into the ‘cache directory’ which was another configurable property.

Although it only took maybe 5 minutes to do this it became quite annoying after a while. If we have found a good enabling point then it should be really easy to switch to using it which wasn’t the case here.

In addition we know had all this impersonating code inside our main solution and it became more and more complex as we tried to make it more useful – another lesson here was that if we’re going to write an impersonator, that code should be outside of our main application.

Self Initializing Fake

The self initializing fake is our current approach and the nice thing about this approach is that it’s really easy to switch back and forth between this and the real end point – all you need to do is change the ‘ServiceUrl’ value in the configuration file!

The self initializing fake is a recording proxy which sits on our CI server and captures the requests and responses to/from the service and then stores those results in memory.

If you make the same request again it returns the response from its store instead of sending that request through to the service layer.

The code for the self initializing fake is outside of our main solution – in fact it’s actually written in Ruby and the application is in C#.

In summary

From my experience it’s quite important to make use of impersonators of our integration points if we are to get a stable environment to run against but we can cause ourselves a lot of pain if we pick the wrong enabling point for that impersonator.

The key seems to be that it should be minimal effort to enable an impersonator and we shouldn’t need to make any changes to our production code in order to do so.

From working with some other impersonators I think it is also important that we shouldn’t have to make any changes to our test code in order to use an impersonator either.

If we find ourselves having to do something that seems crazy with impersonators it might well be worth considering whether we have the right enabling point.

Written by Mark Needham

August 19th, 2009 at 12:43 am

Posted in Testing

Tagged with

Impersonators: Why do we need them?

without comments

I wrote previously about an impersonator we are using on my project which Martin Fowler has dubbed the ‘self initializing fake‘ and although I thought this was the only type of situation where we might use this approach, from discussing this with my colleague Julio Maia and from experiences on the project I’m working on I realise there are other advantages to this approach as well.

To deal with unstable/slow integration points

This is the main reason that we use the self initializing fake and provides perhaps the most obvious reason why we might create an impersonator because we will remain in pain if we don’t create one.

Before we used it all our acceptance tests went from the UI all the way through to the back end via a service layer which often led to tests failing due to timeouts (the service took longer than expected to respond) or problems somewhere in the back end.

These ‘random build failures‘ were amazingly frustrating since it meant that maybe more than 50% of the time that our continuous integration build light was red it wasn’t actually related to anything that the person who checked in had done.

The confidence in the build light had drained and ‘red builds’ were pretty much being ignored.

To speed up the feedback cycle

A nice side effect that we got from putting in an impersonator is that our tests run about 5x more quickly than they did previously due to the fact that the impersonator is on a machine in Sydney whereas the actual end point is on a machine in Melbourne and because the impersonator just returns the same response for a given request each time instead of having to recalculate each time.

It is quite common on projects to use an in memory database instead of the real database for integration tests to allow these tests to run more quickly and I think this logic works well when applied to other systems we need to integrate against as well.

In general if we can have as much of the system as possible under our control in the early parts of our build pipeline then we can have a continuous integration build which gives us very quick feedback and only fails due to problems we created.

To handle not yet ready integration points early

Although we would rather do integration early on in a project so that we can discover any problems and then fix them, sometimes the way the project has been planned means that a system that we need to integrate won’t actually be ready until much later on.

An example of this which I’ve seen a couple of times is integrating applications with single sign on systems.

Even though we don’t know exactly how we will integrate against the real system we might be able to take a reasonably good guess of how it might work e.g. our application is able to detect whether a user is logged in based on some information set in the headers of each request by an ISAPI filter which each request passes through before reaching our application.

On this occasion we didn’t developer an impersonator for this integration point until after we already had the real end point but I think it would probably have made life easier if we had.

Impersonators and Continuous Integration

I’m sure there are more reasons why impersonators make sense but these are the ones that we’ve noticed so far.

The key with all these ways of impersonating an integration point is that they should only form part of our continuous integration pipeline -we do still need to test that our code works in a proper end to end test as well.

In our case we have another stage of our Cruise pipeline which runs all the tests against the real end points.

I’m curious as to what our pipeline should look like when we have built multiple impersonators for different end points – my current thinking is that we can have an early stage of the pipeline where we make use of all of the impersonators and then another stage straight after that where we use all the real end points.

However, it does seem like a bit of a jump to go from all impersonators to no impersonators and it increases the likelihood that the build is going to fail since we are going straight from minimal integration to having everything integrated.

I guess another approach would be to gradually introduce a real integration point on each part of the pipeline until we have everything integrated on the last one although this might actually result in our feedback being slower if its the last integration point which gives us problem.

Julio has written more about the impersonator pattern on his blog.

Written by Mark Needham

August 16th, 2009 at 10:11 pm

Posted in Testing

Tagged with

Test Doubles: My current approach

with 6 comments

My colleague Sarah Taraporewalla recently wrote about her thoughts on test doubles (to use Gerard Meszaros‘ language) and it got me thinking about the approach I generally take in this area.

Stub objects

I use stubs mostly to control the output of depended on components of the system under test where we don’t want to verify those outputs.

Most of the time I make use of the mocking library’s ability to stub out method calls on these dependencies.

I find that it generally seems to require less effort to do this than to create hand written stubs although chatting to Dave about this he pointed out that one situation where it would make more sense to use a hand written stub is when stubbing out a clock/time provider. This is because there are likely to be multiple calls to it all over the place and most of the time you probably want it to return the same value anyway.

I actually quite like the fact that you need to specify all the stub calls that you want to make in each test – it helps you to see when you have too many dependencies and then hopefully you can do something about that.

On previous projects I worked on we decided the way to get around that problem was to define all the stub method calls in a setup method but that seems to lead to a world of pain later on when you forget that you’ve stubbed a method in the setup and now want to assert an expectation on it or (to a lesser extent) write a test which doesn’t actually use the stub.

Fake objects

I often confuse fakes with stubs as seem to be quite similar to each other in their intent – the difference as I understand it is that with a stub we are controlling the output of a dependency whereas a fake just sits there and lets interactions happen with it. The values passed in earlier calls to the fake may be returned in later calls to it.

The most common use of this pattern is to replace a real database with a fake one for testing although on a recent project we were making use of a hand written fake session store to avoid having to refer to the real session in our test code.

We might have one call to the ‘SessionFake’ to store a value and then if a retrieve call is made later on we would return the value that we previously stored.

The approach Sarah describes for stubbing repositories seems quite similar to this as well.

Mock objects

I use mocks to replace depended on components of the system under test when I do care about the way that is is used i.e. we want to verify the behaviour of the dependencies.

If we see a mock object being created in a test then we should see a call to a ‘verify’ method later on to ensure that the expected methods are called on it.

I used to use these all over the place for just about every test where I wanted to control the way that a dependency acted until I realised how fragile and confusing that made the tests.

Now, after recently watching a presentation by Jay Fields, I try to ensure that I’m only setting up one expectation per test and use of the other test double approaches for any other dependencies that needs to be taken care of in that test.

Dummy objects

Most of the time when I pass dummy values into tests they tend to be strings and I prefer to pass in a value of ‘irrelevantValue’ rather than just passing in a null which may lead to difficult to locate Null Pointer Exceptions further down the line if the value which we thought was just a dummy starts being used.

We are generally only passing in these dummy values to satisfy the requirements of the system under test which may require values to be entered even if the particular piece of functionality that we are testing doesn’t make use of them.

Overall

I think my current approach to testing leans more towards mockist rather than classicist although I think I am probably moving more towards the middle as I see the problems we can run into with over mocking.

With test doubles my current approach has minimising the effort required to create them as the most important aspect but I’m sure that will change given a different context. With all the test doubles I generally try and use test data builders where it’s not overkill.

Written by Mark Needham

July 14th, 2009 at 1:23 pm

Posted in Testing

Tagged with ,

TDD: Making the test green quickly

with 5 comments

Although I pointed out some things that I disagreed with in Nick’s post about pair programming one thing that I really liked in that post was that he emphasised the importance of getting tests from red to green as quickly as possible.

I remember the best programming sessions I’ve had was with Stacy Curl, now an ex-thoughtworker and whom I believe was also a chess player. He would always look to quickly make my tests pass, even if it was to just echo the output that my tests would sometimes expect.

The idea that we didn’t have to implement the real functionality after writing the first test for a method was an idea that I feel really freed me up when doing TDD – previous to this I had often spent a lot of time thinking how exactly I wanted to implement the code to make the test pass and I was never entirely satisfied with this approach.

Kent Beck refers to the patterns used to go from red to green quickly as the Green Bar Patterns in his book Test Driven Development by Example.

Fake It

This was an idea which I was first introduced to a couple of years ago while pairing with Dan North – the idea is that if you don’t know how to implement the real code to make a test pass you just do the minimum to make it pass by inserting a fake implementation.

For example, if we have a test checking the calculation of the factorial of 5:

[Test]
public void ShouldCalculateFactorial() 
{
	Assert.AreEqual(120, CalculateFactorial(5));
}

The fake implementation of this would be to return the value ’120′:

public int CalculateFactorial(int value) 
{
	return 120;
}

I’ve found that it actually makes pair programming quite fun when we take this approach as it becomes a bit of a game between the two people to try and come up with a test case that forces the other person to write the real implementation code.

The thing to be careful with here is that sometimes it can actually end up being more complicated faking code for specific inputs and in these cases it may be easier to just implement the solution.

Triangulate

For me triangulating is the next step that we take after inserting a fake implementation to try and drive towards a more generic solution.

The guidance in the book is that we should look to triangulate when we have two or more examples/tests.

In the factorial example perhaps we would drive some example tests which forced us to implement the two parts of the recursive function.

Given we started with CalculateFactorial(5) our next step would probably be to calculate the factorial of 0.

[Test]
public void ShouldCalculateFactorial() 
{
	Assert.AreEqual(120, CalculateFactorial(5));
	Assert.AreEqual(1, CalculateFactorial(0));
}

Leading to an implementation like this:

public int CalculateFactorial(int value) 
{
	if(value == 0) return 1;
	return 120;
}

We now have one example for each branch. The next test would look to drive the implementation of the else side of the expression.

[Test]
public void ShouldCalculateFactorial() 
{
	Assert.AreEqual(1, CalculateFactorial(0));
 
	Assert.AreEqual(24, CalculateFactorial(4));
	Assert.AreEqual(120, CalculateFactorial(5));
}

We could still try to fake the implementation here…

public int CalculateFactorial(int value) 
{
	if(value == 0) return 1;
	else
	{
		if(value == 4) return 24;
		return 120;
	}
}

…although it would probably be easier to just put the obvious implementation in as that’s easier than branching it out for different input values at this stage.

public int CalculateFactorial(int value) 
{
	if(value == 0) return 1;
	return value * CalculateFactorial(value - 1);
}

Obvious implementation

As I alluded to above obvious implementation is where you know exactly how to implement the production code to make your test pass so you might as well just go ahead and write that code straight away.

The trap I’ve run into many times is thinking that I know how to make a test pass by doing the ‘obvious implementation’ before writing way too much code in an attempt to do so – it wasn’t as obvious as I had thought!

This is where the other two approaches can be helpful.

Written by Mark Needham

May 24th, 2009 at 11:43 pm

Posted in Testing

Tagged with