10/09/2005 10:44:00 AM|W|P|Jay Flowers|W|P|

So I have started research for a book that I would like to write.  I am currently looking for  a metric or metric that will indicate when a design is not very testable.  I came across an interesting concept, internal state collapse.  This is where the input parameters are not released from the member.  For example:

public interface IWarehouse

{

    bool HasInventory(InventoryItem inventoryItem, int amount);

 

    void Remove(InventoryItem inventoryItem, int amount);

    void Add(InventoryItem inventoryItem, int amount);

}

The members Add and Remove do not release amount or inventoryItem.  This is known as internal state collapse.  The interest here is that it is very difficult to test.  Lets examine this a little closer.

public void Add(InventoryItem inventoryItem, int amount)

{

    if (this.HasInventory(inventoryItem, amount))

    {

        this.Inventory[inventoryItem] = (int) this.Inventory[inventoryItem] + amount;

    }

    else

    {

        this.Inventory[inventoryItem] = amount;

    }

}

No surprises there.  Some people might say “well just use HasInventory to verify that Add was successful”.  This is fine in production code but test code should try not to use production code to verify production code.  What if there was a bug in HasInventory?  When trying to test Add I don’t want to get sidetracked by a bug elsewhere in the product.  So the problem is that the information needed for verification is not accessible or in other cases has vanished.  After more research I found an answer:

public void Add(InventoryItem inventoryItem, int amount)

{

    if (this.HasInventory(inventoryItem, amount))

    {

        this.Inventory[inventoryItem] = (int) this.Inventory[inventoryItem] + amount;

        System.Diagnostics.Debug.Assert(this.Inventory[inventoryItem] > amount, "The inventory should be more than the amount that was just added.");

    }

    else

    {

        this.Inventory[inventoryItem] = amount;

        System.Diagnostics.Debug.Assert(this.Inventory[inventoryItem] == amount, "The inventory should be that same as what was just added.");

    }

}

This feels a lot like a stint to me.  The assertions act as stints allowing the verification while maintaining encapsulation.  I have seen other solutions that offer information through public members that are conditionally compiled (i.e. encapsulation is only broken for testing).  Any kind of solution that breaks the rules just to achieve testability is a lazy solution in my book (that is the bad kind not the good kind of lazy).  I doubt that the inventors and practitioners of those solutions hold OOP values and principles.  They certainly are not practising them.

Anyway I hope to have the time to finish up the research into testability metrics here in the next two weeks.  If you are interested in this kind of thing you can keep track of my progress in more detail at JayFlowers.com.

|W|P|112887267581991720|W|P|Testability: Internal State Collapse|W|P|10/01/2005 10:08:00 AM|W|P|Jay Flowers|W|P|I have been doing a lot of research lately on how to teach unit testing.  There seem to be to basic forms: State and Interaction.  In my last post I define what a unit test is in a very strict way.  By that definition I can not see how state based testing is unit testing.  I wanted to refer to my own examples here but gotdotnet user samples take 72 hours or so to be published so I will refer to Martin Fowler’s Mocks Aren’t Stubs.  At the beginning of this article he illustrates the two approaches.  For state based testing to be performed a portion of the system, more than the test subject, was needed.  It was needed for the test subject simply to be used.  Sniff Sniff Sniff.  Do you smell that.  Smells like tight coupling to me.  Bugs in the warehouse class can easily cause the order unit test to fail.  This fail to express much of the potential value of a unit test.  Indicating were the problem is.  Now we can only know that when a unit test fails that it's a problem in either the order or warehouse classes.  So why would I write a separate unit test for the warehouse class, I don’t really even feel like adding asserts to the order test to verify that the warehouse object is in the expected state.  All this leads me to believe that state based testing is not a unit testing style at all.  It promotes bad practices.  This is not to say that it isn’t a great style for other forms of testing, just unit testing.  Interaction testing on the other hand is dependent on loose coupling; same as the definition in the previous post depends on it.|W|P|112817932455542819|W|P|State Based UnitTesting, or Not?|W|P|