Showing posts with label Interaction Testing. Show all posts
Showing posts with label Interaction Testing. Show all posts

Tuesday, March 25, 2008

Trying For Readable Tests

Whilst playing with using BDD style specifications to drive the granular design of my classes I've tried to see if I can also look at ensuring my tests are as readable as possible and I thought I should document my current thoughts on the results.

In this description I'll use the word specification/test interchangeably...I'm just not ready to talk about state or interaction specifications.

State Tests

I've been following the approach of having small test fixtures (contexts), for example:

using Concerning = System.ComponentModel.CategoryAttribute;
using Specification = NUnit.Framework.TestAttribute;
using Context = NUnit.Framework.TestFixtureAttribute;
using NUnit.Framework;

namespace AddressMapperSpecifications
{
[Context]
[Concerning("AddressMapper")]
public class When_mapping_addresses
{
#region Fields

private AddressDetails _mappingFrom;
private Address _mappingTo;

#endregion

# region
Context

[SetUp]
public void SetupContext()
{
_mappingFrom = AddressObjectMother.CreateAddress();

_mappingTo = new AddressMapper().Map(_mappingFrom);
}

# endregion

#region
Specifications

[Specification]
public void Street_one_is_mapped()
{
Assert.AreEqual(_mappingFrom.StreetOne, _mappingTo.StreetOne);
}

[Specification]
public void Street_two_is_mapped()
{
Assert.AreEqual(_mappingFrom.StreetTwo, _mappingTo.StreetTwo);
}

I like this style because it leads me to have small fixture/context classes, likely only a very few specifications are going to want to share exactly the same fixture so I avoid the issue of my classes getting too big.

I also think that the small fixture size and the class/test names together result in an approach that I find very readable.

Interaction Tests

As I see it you use use mocking for a few reasons, one of the most obvious ones is to for convenience. Say A calls B which calls C, if I write my tests for C but my clients use A then I need to show that when I call A we can expect C in turn to be called (and also can show the arguments/return values). I see this as mocking to make granular testing easier, there are other reasons to use mocking/stubbing but this discussion doesn't necessarily relate to them so well.

The previous example showed a state test/specification where just having an assertion (or assertions) in the specification method worked. Arguably moving the setup and interaction with the system under test (SUT) into the SetupContext method helped make it all more readable. We can't really do that so easily with mocking tests because in a mocking test you have to setup your expectations up front so the tests take take (basically) this form:

  1. Setup including setting expectations on the mock.
  2. Exercise the SUT.
  3. Verify that the expectations on the mock were met and optionally do other verifications.
  4. Cleanup (if required).

If we move the setting up of the mocks into the SetupContext method then we'd end up with a situation where each class had one specification (because its unlikely we'll want to setup the same expectations multiple times). Even worse looking at the specification method would tell you nothing because to understand a mocking test you need to start by looking in detail at the expectations.

I've thus found that so far my interaction tests are taking this form:

namespace AccountMessageMapperSpecifications
{
[Context]
[Concerning("AccountMessageMapper")]
public class Interactions_when_mapping_an_account : RhinoMockBase
{
# region Fields

private Account _subjectOfMessage;
private DomainMessage _messageToBeMapped;

private AccountMessageMapper _underTest;

# endregion

#region
Context

[SetUp]
public void SetupContext()
{
_subjectOfMessage = AccountObjectMother.CreateAccount();
_messageToBeMapped = new TestDomainMessageBuilder().WithDomainEntity(_subjectOfMessage).Build();

_underTest = new AccountMessageMapper();
}

#endregion

#region
Specifications

[Specification]
public void Primary_address_is_mapped()
{
IMapper<IAddress, Address> _mapper = Mocks.CreateMock<IMapper<IAddress, Address>>();

using (Record)
{
Expect.Call(_mapper.Map(_subjectOfMessage.Owner.PrimaryAddress)).Return(new Address());
}

using (Playback)
{
_underTest.Map(_messageToBeMapped);
}

_mocks.VerifyAll();
}

#endregion
}
}

DISCLAIMER: I've just bodged this together so it isn't great. I'm particularly not liking the way it looks when I pass a generic interface in to get a mock for it!

Most of the code is in the actual specification method, including all of the setup, the interaction with the SUT and finally the call to verify that the expectations were met. I've moved as much as I think I sensibly can into the SetupContext method but the fixture is still quite lightweight and reusable, for example I could easily put another method in that showed the interaction with another mapper (e.g. Telephone_number_is_mapped).

Overall though I think this style of interaction test is quite readable, and to me the combination of the two tests explains very well the behaviour of a low-level component (AddressMapper) and also the interaction that a higher level component (AccountMessageMapper) has with it.

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

Saturday, February 02, 2008

Test Spy - Replacing Services When Testing The Domain

At the recent discussion of mocking at ALT.NET UK we discussed using test spies.

We actually make good use of test spies now and they have some advantages. Let me give you an example where they come in handy. Our domain classes occassionally need to contact external services, interfaces implemented by these services are put in the domain (seperated interface) with the implementations available to the domain using a Service Locator.

What do to when testing though, we have maybe 1% of the the tests where we need to setup a mock version of the service and the rest don't care about the service so they can run with a do-nothing stub.

However if we register a mock version of the service with the Service Locator and if we forget to cleanup propely then that mock service will affect other tests. Its also painful having to put the stub service back in after you are doing using the mock.

The solution, suggested by one of my colleagues, is simple. We don't ever mock the service but instead we use a test spy. We register the Test Spy with the Service Locator in a method tagged with AssemblyInitializeAttribute so it gets run before any tests in that assembly.

All the normal tests run normally, and if they in some way cause the system to interact with the test spy then the interaction happens totally silently, for example maybe the test spy logs the interaction by adding an item to an internal collection.

So what about the 1% of the tests that really want to test against the test spy (the tests that might otherwise have used a mock). Well in the test fixture initialization we reset the test spy then at the end of each test we ask the test spy what calls it received and verify that they were what we expected.

This works a treat, really simple solution that makes the tests very easy to write.

NOTE - When to call services from the domain
The comment from Andreas made me realize that I didn't say when I think a domain class should talk to a service.

Normally I avoid these sorts of dependencies in order to keep the domain code clean, simple and easily testable. However for cross cutting concerns like logging/dirty tracking an AOP based approach (see my PostSharp posts) where we introduce the code that calls the service is very clean.

In particular this works because for those cases we can have the domain class contact the (infrastructure) Service but we don't care about any return values, hence the applicability of a Test Spy.

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

Wednesday, January 23, 2008

Styles Of TDD for your Domain Model

Having read a lot of mockobjects.com I'm beginning to understand need-driven development and the effect on design. This has made me want to re-read some old articles:

These are all good posts but I'm coming to the conclusion that there just isn't that much real content out there about how to use interaction testing as a design and testing activity for domain entities/value objects. Seems like a lot of people don't do it and so far the ones that do haven't written that much about it.

The content I have found has semed to be producing designs that I wouldn't be that interested in and although the idea of extracting role interfaces from high level domain entities interests me I can't find any real evidence that people are doing it meaningfully. I'm also not sure that doing it is going to improve the design that much.

Anyway I think for now I'm better focussing my design efforts on traditional DDD activities, whilst keeping an eye on what the BDD/mockobjects.com guys produce.

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

Tuesday, January 22, 2008

Interesting Posts About Tests Influencing Design

Oddly I started reading a post by Jay Flowers, which led me to re-read a linked post at mockobjects.com which in turn led me to the most relevant post of all about testing domain classes. I'm glad I followed the links because there is some good info in these posts.

Shifting The Focus
Jay Flowers is thinking about testing and design at the minute too and has just posted about how it affects design in a post called Shifting The Focus.

Test Smell : Everything Is Mocked
I read the post Test Smell: Everything is mocked some time ago but never blogged about it but I do definitely think its worth reading.

I fully agree with the post, directly mocking external API's is often going to be a mistake and your better to use TDD to evolve a wrapper. I also think mocking value objects is a bit of a no-no.

Note there is a TDD thread related to mocking value objects.

Testing Domain Classes
J. B. Rainsberger has a post called A sign you're mocking too much which I whole heartedly agree with.

One of the main points in the post is summed up in this line "Never mock values, sometimes mock entities, but mock services freely". I agree with this and that's basically the way I test domain classes too:

  1. Value Objects - No reason to mock, they should be simple to construct.
  2. Entities - I tend to create real instances using Object Mother or Test Data Builder objects. Occassionally I'll stub an entity but very rarely will I mock it.
  3. Services - Mock away, including mocking repositories.

This also ties in nicely with Eric Evans' opinions from the Testing The Domain thread on the DDD forum. It also indicates that some DDD practitioners (including myself) are using TDD to influence design in ways other than those that we would get to if we purely used interaction testing.

I think I'm going to start to focus on looking at our domain tests and object mothers to see what they are telling us about problems with our current designs.

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

Monday, January 21, 2008

How You Test = How You Design

I've recently started reading through all the design related posts at mockobjects.com.

They are highly recommended and I agree with all of the theory behind them and a lot of the practices. However what interested me most was that despite this I don't design software in the same way as them.

Take the "Test Smell: I need to mock an object I can't replace (without magic)" post as an example. I love the design exercise that the author goes through, and extracting the Clock/SameDayChecker class is superb. Yet something about it made me realize that I don't design the way they do and amn't sure I want to...

Refactoring v Need To Mock
In the example the design improvement is driven by the need to replace the time in a test.

Now I can understand the need to replace the time but I would also say that if your the sort of designer than looks at the original code and sees that its not cohesive enough then your going to extract the SameDayChecker concept regardless.

Maybe I'm wrong though, would I have looked at the original code and thought "good enough". Possibly, and if there was no pain then that might have been fine. So the tests have perhaps forced us to a better design.

However that leaves me a little cold as if we didn't need to replace the time for testing, or if the incohesive code had nothing to do with an external dependency, then we'd have settled for the first option.

If we thus use this style of testing to drive our designs then we only get good designs if we make every piece of the code replacable...

Injection
I dunno but to me the whole IoC thing is heavily influenced by Robert Martins ideas of dependency inversion.

Thing is I don't think Robert Martin meant that every class should be replacable, or at least I never read it that way.

I also don't think it should be used as your primary design technique, as in I want to test Customer without CustomerMustHaveAddressRule so i'll extract the rule (good) then inject it into Customer (huh). Do I really need to inject my rules into the domain, if I do then fine but for many line of business applications this would be overkill.

My approach would be extract the rule (SRP/cohesion etc.) but then use it directly from the domain. I'm unlikely to replace one rule with another implementation.

Why It Matters
I actually think using interaction testing as a design technique is interesting but when I look at the Clock/SameDayChecker example I'm left a little unhappy.

Am I really going to ever replace the SameDayChecker in production, is it really a meaningful dependency that I want my domain class to show. To me the answer is "probably not" to both.

I also think that IoC and injection of dependencies is great. However I definitely do not think everything needs to be injected when it comes to domain models, and if you use the design technique described then I think that you could end up with decoupling that I wouldn't find useful.

Lots of decoupling, much of which does nothing but make the design more complex without ever being taken advantage of, is my worry with some of these techniques.

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

Roy Osherove - The Case For TypeMock

Roy Osherove has another post on the case for TypeMock.

For me the big one is that design for testability has its limits. Breaking encapsulation, interfaces over all your classes, injecting everything, virtual members everywhere. Those things can be good and they can also lead to klunky designs particular in domain/business code).

That doesn't mean that design for testability isn't good. However when I want to mock something without changing its design, because I'm quite happy with its current design, I turn to TypeMock.

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

Sunday, January 20, 2008

Test Doubles and the Effect On Designs - Mock/Stub/Fake

Just got through reading the mockobjects article on the interaction test smell too many expectations.

It's a great article and made me want to try to bring together my understanding of what people mean when they talk about stubbing and mocking.

MockObjects.com - Stubs and Expectations
The article makes the distinction between Stubs and Expectations:

  1. Stub - Replace a dependend on component (DOC) so that you can get it to return known values.
  2. Expectation - Goes further by testing that we get the expected interaction with the DOC.

The idea is that if you program too many expecations into the test you get confusing tests that don't make it clear whats important.

XUnit Test Patterns - Stubs and Mock Objects
If you have read Meszaros's XUnit Test Patterns then you will know that in his view there are multiple types of Test Double and they are required to control two things:
  1. Indirect Inputs - If the system under test (SUT) uses the DOC and the DOC returns any values (even exceptions) that affect the SUT then you need to be able to make the DOC return these values in order to run your tests. If you can't get the DOC to do it then you replace it with a Test Double.
  2. Indirect Outputs - Encapsulation often means we don't have to care how an object does what it does, however when testing we do care and we therefore may want to test the interactions with the DOC (in the process writing the SUT to make its dependency on the DOC more obvious). In fact in some cases we may have no choice if the DOC does not produce any observable side effects.

Meszaros goes further and describes the means of getting the correct inputs into the SUT in as being through a control point and the means of verifying the indirect outputs as being through an observation point.

In Meszaros's terminology there are thus three main types of Test Double:

  1. Test Stub - Controls indirect inputs to the SUT.
  2. Test Spy - Acts as a Test Stub but also records calls so that the test can examine them.
  3. Mock Object - You pre-program it with the expected interactions and it will verify they happened.

Meszaros also discussed further classifications and how to configure/install the Test Doubles, as with the rest of the book it is very comprehensive.

Why It Matters
It seems like people are coming to the conclusion that it is important to differentiate between situations where you care about the expected interaction with an object and cases where you don't. If you don't make the differentiation your tests will be unnecessarily complex.

The interesting bit is then how the different types of Test Double affect your testing. I believe many people use Mock Objects when they really don't much care about the collaborations and aren't using the mocking as an aid to design. In fact the mock object is often simply there to replace a DOC so that we can simplify or speed up the test. This is at odds with the design technique that mockobjects.com and "Mock Roles, Not Objects" are recommending. As I understand it they view the outside-in process of design as being a big advantage of using interaction tests and use that to drive their designs (Need-Driven Development).

Its the second issue, how tests affect design, that interests me at the moment.

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