1

I am working on a large test project consisting of thousands of integration tests. It is a bit messy with lots of code duplication. Most tests are composed of several steps, and a lot of "dummy" objects are created. With dummy I mean something like this:

new Address {
    Name = "fake address",
    Email = "some@email.com",
    ... and so on
}

where it often really doesn't matter what the data is. This kind of code is spread out and duplicated in tests, test base classes, and helpers.

What I want is to have a single "test data builder", having a single responsibility, generate test data which is consumed by the tests.

One approach is to have a class with a bunch of static methods like following:

Something CreateSomething(){
    return new Something {
    // set default dummy values
}

and an overload:

Something CreateSomething(params){
    return new Something {
    // create the Something from the params
}

Another approach is to have xml files containing the data but i am afraid then it would be too far away from the tests.

The goal is to move this kind of code out of the tests because right now the tests are big and not readable. In a typical case, of 50 lines of test code, 20-30 is of this kind of code.

Are there any patterns for accomplishing this? Or any example of big open source codebase with something similar that I can have a look at?

Mr Balanikas
  • 1,657
  • 15
  • 28

2 Answers2

1

I would shy away from xml files that specify test dependencies.

My thought process stems from a lack of refactoring tools that these xml files cannot take advantage of within the Visual Studio ecosystem.

Instead, I would create a TestAPI. This API will be responsible for serving dependency data to test clients.

Note that the dependency data that is being requested will already be initialized with general data and ready to go for the clients that are requesting the dependencies.

Any values that serve as required test inputs for a particular test would be assigned within the test itself. This is because I want the test to self document its intent or objective and abstract away the dependencies that are not being tested.

XUnit Test Patterns provided me a lot of insight for writing tests.

Scott Nimrod
  • 11,206
  • 11
  • 54
  • 118
  • what exactly do you mean by a TestAPI, implementation-wise? a fluent test api, static "pure" methods, something else? thx for the book tip :) – Mr Balanikas Feb 25 '15 at 19:56
  • An example: See unit test section of my post... http://stackoverflow.com/questions/26871519/construct-testable-business-layer-logic/26871728#26871728 – Scott Nimrod Feb 25 '15 at 20:00
1

For code, use a simple method chaining builder pattern:

public class TestOrderBuilder
{
    private order = new Order();

    //  These methods represent sentances / grammar that describe the sort   
    //  of test data you are building
    public AnObjectBuilder AddHighQuantityOrderLine()
    {
         //... code to add a high quantity order line

         return this; // for method chaining
    }

    //  These methods represent sentances / grammar that describe the sort   
    //  of test data you are building
    public AnObjectBuilder MakeDescriptionInvalid()
    {
         //... code to set descriptions etc...

         return this; // for method chaining
    }

    public Order Order
    {
         get { return this.order; }
    }
}

// then using it:
var order = new TestOrderBuilder()
                 .AddHighQuantityOrderLine()
                 .MakeDescriptionInvalid()
                 .Order
James Simpson
  • 1,150
  • 6
  • 11
  • +1 for another answer I would have written but you beat me to...:) Just curious, how do you handle the problem where you do a "default" setup on a mock in one method but then you want to add more to it later in another method? Most mocking frameworks usually blast away any previous setups if you define the same setup again. For example using Moq, how do I set a `.Returns` in one method, but then define a `.Callback` in another method (or directly in my test)? My workaround is to either copy the `.Returns` into said callback-setting area or maintain a collection of the setups. – moarboilerplate Feb 26 '15 at 15:51
  • 1
    I don't beleive I have had to do that yet. When using Moq the setups are usually very concise, and to be honest I tend not to use callbacks anyway, usually it's Just OK to verify the method call with given parameters in the assertion. You could however apply the same Builder pattern for building your Mock ? – James Simpson Feb 26 '15 at 16:48
  • Yep, I've taken that approach and I also have experimented with mixing in functionality with Mocks using Castle.DynamicProxy as well..quite the adventure! – moarboilerplate Feb 26 '15 at 16:58