Where can I find wonton wrappers at Meijer

One man think tank thoughts

Design for Testability is also Design for Flexibility. That's why I love TDD. However, I kept stumbling across one problem: checking the status of a system under test (SUT). As an example, here is a typical (not necessarily optimal) approach for the well-known and popular KataPotter.

When implementing the price calculation for the KataPotter, many think of a shopping cart that has to be filled in order to then calculate the price using the discounts. You then define such a class as follows, for example:

classKataPotterShoppingBasket

{

privateDictionary books = newDictionary ();

 

publicvoid AddBook (int bookId)

    {

        //...

    }

 

public decimal total

    {

get

        {

            //...

        }

    }

}

A related test seems simple at first:

[TestFixture]

publicclasstestKataPotterShoppingBasket

{

[Test]

publicvoid contains_a_book ()

    {

var sut = newKataPotterShoppingBasket ();

 

sut.AddBook (1);

 

        //?

    }

}

But, oh, oh dear ... How do you check whether the added book has also arrived in the shopping cart? AddBook () is a command and changes the status of the shopping cart. So how can you generally check this state in tests?

Access routines for state?

The obvious thing to do is to check the status through direct access to the status. For this, the SUT only has to offer such access. This may be the case for a normal shopping cart. There is not only an AddBook (), but certainly also a GetBook () or a whole collection of books that can be used to check whether a change in status was effective.

The KataPotter shopping cart does not need such access routines. So why should they only be introduced for the test? I don't think so because they inflate the interface of the system under test. They have no value for the domain, but are always visible in the Intellisense list of properties and methods. The declaration as internal doesn't help much either. That would be a misunderstood Design for Testability.

If you should approach the KataPotter as shown above, resist the temptation to give the shopping cart a count property, for example, in order to get the test to work.

Such a design would be somehow more testable, but the flexibility would not increase. They would no longer have done the bare minimum. In addition, the test would then test two things. That is to be avoided! He would check AddBook () and Count. There could be mistakes in both.

AddBook () and Count would even be interdependent for tests. You could not test Count first either, because you would have to establish state to do so. If this were not the case, the use of several SUT functionalities in one test is not so bad. Then you can check them in advance in separate tests.

Result: Avoid setting up special state access methods for testing purposes only. Anytime you can't really test it in isolation.

State test by derivation?

You can not only access the state from the outside, it is easier from the inside. An alternative to access methods would therefore be to derive a class from the SUT. Their condition would be that of the shopping cart. To do this, you would just have to change the visibility of the state:

classKataPotterShoppingBasket

{

    protectedDictionary books = newDictionary ();

    ...

}

A derivation can then "safely" offer an access method. This does not "contaminate" the domain class:

classTestableShoppingBasket: KataPotterShoppingBasket

{

publicint Count {get {returnbase.books.Count; }}

}

If you instantiate the derived class as an SUT in the test, you have testability “without regrets”:

[Test]

publicvoid contains_a_book ()

{

var sut = newTestableShoppingBasket ();

 

sut.AddBook (1);

 

Assert.That (sut.Count, Is.EqualTo (1));

}

With a derivative, you don't even have to do Design for Testability. And flexibility is not restricted either. A seemingly ideal solution, right? The interference to set private variables to protected instead of private is minimal. And that this approach fails with sealed classes is also irrelevant.

Nevertheless, I don't really like a derivation from the actual SUT. No, that's not because I think derivatives are generally overrated. Even the Liskov Substitution Principle would have been adhered to here. I don't find the effort for the derivation class too high either.

No, there is something else that bothers me ...

State as dependence

I think it bothers me that Zustand gets an extra sausage fried here. Condition is not treated by its nature. Because state is a dependency!

When we think of dependencies, we usually think of functionality. The shopping cart could e.g. depend on a price calculation functionality:

Then we'd find it natural to inject this addiction into the shopping cart:

classKataPotterShoppingBasket

{

privateIPriceCalculator calc;

privateDictionary books = newDictionary ();

 

public KataPotterShoppingBasket (IPriceCalculator calc)

    {

this.calc = calc;

    }

    ...

But what is the private calc field now? It is just as much a part of the state of the shopping cart as it is books. The only difference is that calc is of a self-defined type and book is of a .NET Fx type.

In addition, we believe that we somehow feel a greater "intimacy" between book and e.g. AddBook (). The contents of book are changed using the shopping cart method, while calc remains constant. book is just the “true” state and should therefore be treated differently than calc.

But why is the dependency on a price calculator disclosed? Why is it being injected? Because this makes the shopping cart testable in isolation. You can put him to the test by injecting a dummy. In addition, the price calculation can be exchanged even more flexibly; a nice side effect.

However, if better testability has now led to the IoC for functional dependencies, why shouldn't it also be used for state dependencies? I don't see any weighty counter-argument. That would not contradict the object orientation either. After injection, the state is still hidden in an object according to its access methods.

So when we talk about addictions, we should be consistent. State and behavior are two sides of the same coin dependency:

From my point of view, the solution to the initial problem looks like this:

classKataPotterShoppingBasket

{

privatereadonlyPriceCalculator calc;

privatereadonlyDictionary books;

 

public KataPotterShoppingBasket (Dictionary books,

PriceCalculator calc)

    {

this.calc = calc;

this.books = books;

    }

    ...

You inject not only the dependency on a price calculation functionality into the extended shopping cart, but also an initial state:

[Test]

publicvoid contains_a_book ()

{

var books = newDictionary ();

var sut = newKataPotterShoppingBasket (

books,

zero);

 

sut.AddBook (1);

 

Assert.That (books.Count, Is.EqualTo (1));

}

I think that is just as consistent as it is easy to understand. The pattern then reads somewhat systematically:

  1. Combine the dependencies of a class in a dependency class. This applies to states such as functionality on which a class depends.
  2. During tests, inject the minimum necessary dependencies with an instance of the dependency class.
  3. Check expectations of state changes after executing commands on the SUT using the injected dependency class instance.

Using the shopping cart as an example, it would look like this:

classKataPotterShoppingBasket

{

internalclassDependencies

    {

publicreadonlyIPriceCalculator calc;

publicreadonlyDictionary books = ...

    }

 

 

privatereadonlyDependencies dependencies;

 

public KataPotterShoppingBasket (Dependencies dependencies)

    {

this.dependencies = dependencies;

    }

    ...

The test would be even a little clearer, I think:

[Test]

publicvoid contains_a_book ()

{

var dependencies = newKataPotterShoppingBasket.Dependencies ();

var sut = newKataPotterShoppingBasket (dependencies);

 

sut.AddBook (1);

 

Assert.That (dependencies.books.Count, Is.EqualTo (1));

}

The “normal” dependency injection does not stand in the way of this process. She would even hide it. For this purpose, the dependency class would only need a designated "channel" for injecting the functionality on which the shopping cart is dependent, e.g. for Unity as a DI container:

publicclassDependencies

{

[Dependency]

publicIPriceCalculator calc {get; set;}

publicreadonlyDictionary books = ...

}

In addition, the dependency class would have to be listed in the mapping. But that is not a special extra effort. That could possibly even be automated.

Conclusion

In terms of a systematic approach to testing and design, I think it is very worth considering to define dependencies more broadly than before. Functional units are not only dependent on other functional units, but also on condition.

If dependencies are then to be injected in order to achieve better testability, then this applies not only to functional units, but also to status.

With TDD in particular, this reduces - so my feeling - the intellectual effort. With every command and every query that is tested, you then simply have to ask yourself which state plays a role. Then, before the test, you assemble (arrange) the initial state specifically for the test case and inject it, call the SUT (act) and then check (for commands) the new state (assert). Finished.

In the near future, I'll be doing this consistently on a trial basis. Let's see how that feels. I am optimistic it will feel good. Less doubts, less thinking, so higher productivity.