TDD Pattern: Composite Logic Development and Testing

Here's a video I made that captures my current thoughts on writing complex business rules which have lots of validation logic.

Here's the scenario I show in the video:

image

A Validate method on an object actually uses lots of smaller methods to return a result. The idea is to actually write separate tests for the underlying helper methods (which are actually individual rule checks) and a separate test for the overall logic driver (the Validate method.

Different from traditional TDD technique

This is different from the traditional way I would do TDD in that in the traditional sense, in TDD you probably would not have these helper methods but would actually write all that logic inside the validate method, and only later you would refactor the code into separate smaller methods.

  • TDD: Start with a simple method and refactor it into smaller methods if and when you need to while making the tests pass.
  • This method (Composite Logic TDD - CLTDD???): drive the creation of the separate rules as part of the TDD effort (part of the initial design).

But why? Because every time I tried to accomplish the same thing with the traditional way I came up with problems thinking about my next tests. every time I would add another rules to the implementation it would break my existing tests because they had to account for my new rule.

In the new method I gain full control over what the rules actually return so that I can tell the validate method - "Assume that all the rules pass, except this one". then I can go on and test things separately. here's what I mean:

image

So the video details how you would write all this in a test driven manner. I'm personally not entirely happy with it and i think the technique is still rough around the edges (takes time to learn, not very intuitive etc..) but it's currently the only way I could come up with to test the logical driven separately from the individual rules it uses.

 

Separation of concerns

The thing I like about the end result is that the individual rules methods (HasDIgit() etc..) can be coded and tested independently from the logic that uses them. much like separating a call to a web service from the actual web service implementation and testing them separately.

Your input is welcome. I'm looking for:

  • Giving a proper name for this technique\pattern (the XUNit test patterns book calls the pattern "Test Specific Subclass" with the variation of "Behavior changing subclass"   but what I'm doing is a pattern for TDD that tests a composite logic piece of code. what should we call this technique?
  • Tell me where I'm missing something in the technique that could lead to potential problems
  • tell me if you think you have a better way of accomplishing this (in TDD or not)

 

 Here's the video, 44 minutes.(the demo of the validate method starts at minute 21)

in the video(you can also download it 57 MB):

  • understanding the problem
  • the different kinds of tests for this problem
  • a simple demo of the extract and override pattern
  • the full demo of using the Validate method

here are the slides for this video.

Published Tuesday, September 18, 2007 8:32 AM by RoyOsherove

Comments

Tuesday, September 18, 2007 9:25 AM by Diego Carrion

# re: TDD Pattern: Composite Logic Development and Testing

Everything seems cool to me except the name of the function "HasMax10Chars".

What if tomorrow the maximum length turns 11?

Shouldn't it better to have a function called like "HasValidLength" or something similar?

Tuesday, September 18, 2007 1:10 PM by Vish

# re: TDD Pattern: Composite Logic Development and Testing

Hi Roy,

I have run into a whole lot of problems with Validate functions that returns a boolean in the past. They are not flexible enough. I have adopted creating the validation rules into a IRULE interface. The actual validation can actually be done by a delegate that is a property of the IRULE. So now the Validate function can return a List<IRULE> which will facilitate more meaning error messages etc.

Thank You,

Vish

Tuesday, September 18, 2007 2:12 PM by Steve Campbell

# re: TDD Pattern: Composite Logic Development and Testing

I have found it not really worthwhile to unit test simple field validations.  Doing so does not drive "design", so it only fulfills the "test" aspect of TDD.  That is a sign that something can better be tested elsewhere, and as it happens validations map very closely to business rules, so they can be adequately tested at a higher level (acceptance tests ala FIT).

Tuesday, September 18, 2007 2:31 PM by Jan Van Ryswyck

# re: TDD Pattern: Composite Logic Development and Testing

Hi,

Instead of using seperate methods, I'll like the approach of using "specifications" as outlined by Eric Evans and Martin Fowler:

martinfowler.com/.../spec.pdf

I'm using Tim McCarthy's Composite Specification Pattern Implementation for this.

blogs.interknowlogy.com/.../10863.aspx

This way I can keep using TDD and I can reuse specifications between several classes that have a Validate method. It also makes the business rules explicit in my model.

Let me know what you think ...

Tuesday, September 18, 2007 5:07 PM by RoyOsherove

# re: TDD Pattern: Composite Logic Development and Testing

Vish: you're assuming all "rules" have the same inputs, which might not be the case. they might also have different outputs. How would you hand;e that?

Tuesday, September 18, 2007 5:37 PM by RoyOsherove

# re: TDD Pattern: Composite Logic Development and Testing

Jan Van Ryswyck:

in essence, my implementation is that of a hard coded specification. just change the name of "Validate" to "IsSatisfiedBy" and think of each of the protected methods as leaf specifications.

the Validate method is a composite hard coded specification. the problem is still - how to you test (or rather TDD) that the correct composite specification is being built? so I want my test to fail if my IsSatisfiedBy method isn't using the leaf specifications as it should (which means it's logic is flawed).

Tuesday, September 18, 2007 5:41 PM by RoyOsherove

# re: TDD Pattern: Composite Logic Development and Testing

Diego: yeah, the name might be a bit too much but that's what refactoring tools are for.. :)

Tuesday, September 18, 2007 6:11 PM by RoyOsherove

# re: TDD Pattern: Composite Logic Development and Testing

Diego: yeah, the name might be a bit too much but that's what refactoring tools are for.. :)

Wednesday, September 19, 2007 12:24 AM by Vish

# re: TDD Pattern: Composite Logic Development and Testing

Hi Roy,

Using generic delegates gets you half the way there

And using a delegate definition like

delegate void CustomValidate1<T>(T value, List<T> others);

   delegate void CustomValidate2<T>(T value, List<object> others);

might help you out further. But yes they are hacks but i found them to be better.

And the output of rules are almost always messages that can be made a property of the rule itself or a new type for validation results can be created and a list of the broken rules or the validation result type can be returned by the validate function.

Thank You,

Vish

Saturday, September 22, 2007 8:30 PM by Avi Naparstek

# re: TDD Pattern: Composite Logic Development and Testing

Hi Roy.

I enjoyed the post - although I havn't finished viewing the entire video yet, it got me writing about my own experience test-driving composite validation methods here:

asynced.blogspot.com/.../testing-everything.html

I'd be interested to hear what you think.

Some comments about the video (so far):

1. Seems like the testable-subclass demo is stealing the spotlight away from the issue of composition.. Have you considered seperating the two?

2. It seems like you are pre-assuming a design here - specifically that you'll have a Validate() method using smaller Has6Chars(), HasDigits() etc methods. It might be interesting to demonstrate how the code evolved towards a solution rather than see how to unit-test an existing (or pre-cincieved) solution.

All the best and keep 'em coming,

- Avi

Friday, September 28, 2007 10:17 AM by Donny Darko

# re: TDD Pattern: Composite Logic Development and Testing

Hi - I must confess I am not a TDD expert, but seeing this video really had me raise my eyebrows.

The scenario is that you are developing a framework, that should be used within your company. you want to TDD the framework (which i believe is a good thing!). then you start using different patterns that allow for the framework to be testable (good), but meanwhile you make consessions with regards to your public API (bad).

I could easily see myself in a situation in which I would have to explain... yes, well... the Fx design is kinda awkward. but this was just the easiest way to test the Fx.

:-S