Programming  /  Testing July 12, 2009

Best practices when testing large but simple methods?

Lately, both at work and when working with the Page Type Builder project, I’ve been writing tests that tests methods that are very simple but quite long. While doing this I’ve been struggling with what tests I should have and how the tests should be written.

Let's say I have a large method that contains quite a lot of operations that are on the same level of abstraction. It could for instance be a method that updates a object based on some other object. Like this (imagine there are like thirty assignments instead of just two):

void UpdatePage(Page page, PageSpecification specification)
{  
    page.Name = specification.Name;  
    page.Type = specification.PageType;
} 

One way of testing this method would be to create three different tests that tests each of the assignments, like:

void GivenSpecification_UpdatePage_updatesPageName() 
{   
    PageSpecification specification = new Specification();   
    specification.Name = Guid.NewGuid().ToString();   
    Page page = new Page();   
    
    UpdatePage(page, specification);  
    
    Assert.Equal(specification.Name, page.Name); 
}

Another alternative would be to create a singe test in which I create a expected object and compare the updated object with that. Like this:

void GivenSpecification_UpdatePage_updatesPageName() {   
    PageSpecification specification = new Specification();   
    specification.Name = Guid.NewGuid().ToString();   
    specification.Type = new PageType();   
    Page page = new Page();   
    Page expectedPage = new Page();   
    expectedPage.Name = specification.Name;   
    expectedPage.Type = specification.Type; 
  
    UpdatePage(page, specification);   

    AssertPageEquals(expectedPage, page); 
} 

A third alternative would be to break up my method in separate, smaller, methods that I test individually. I would then test the main method by making the helper methods virtual, create a partial mock and test that the main method calls each of the helper methods.

I'm leaning towards the third alternative as it makes it very clear what functionality is broken when a test fails while keeping the tests simple. It will however require me to make the helper methods virtual for no other reason than to test them.

Any (preferably well motivated) suggestions are greatly appreciated!

PS. For updates about new posts, sites I find useful and the occasional rant you can follow me on Twitter. You are also most welcome to subscribe to the RSS-feed.

Joel Abrahamsson

Joel Abrahamsson

I'm a passionate web developer and systems architect living in Stockholm, Sweden. I work as CTO for a large media site and enjoy developing with all technologies, especially .NET, Node.js, and ElasticSearch. Read more

Comments

comments powered by Disqus

More about Testing