Also on twitter ( twitter.com/nutrun )

Archive for the ‘TAPD’ Category

Test Code and Production Code – two distinct beasties

Wednesday, April 18th, 2007

“Test Code and Production Code – two distinct beasties”. Better late than never, they say…

The Testing Anti-Patterns Drafts: Overusing Mocks

Tuesday, November 28th, 2006

There is something problematic about Mocks. They are just too convenient. Developers are lured into employing them all over the place, often forgetting Mocks’ primary function. And that is not the convenience of satisfying the dependencies of the code under test.

Mocks’ main purpose is to test interaction between Objects. This is why Mock verification is performed upon expectations of method calls. One of the golden rules of Unit Testing is testing one thing at a time. In this context, if there is more than one Mock per test case, this rule is probably broken.

public class CustomerServiceTest extends TestCase {

  public void testShouldSaveCustomerDetailsWithRepository() {
    Customer customer = new Customer("Kirk", "Hammet");

    CustomerRepository repository =
        EasyMock.createMock(CustomerRepository.class);
    AuditLog log = EasyMock.createMock(AuditLog.class);

    repository.save(customer);
    log.logCustomerSaved(customer);

    EasyMock.replay(repository);
    EasyMock.replay(log);

    new CustomerService(repository, log).save(customer);

    EasyMock.verify(customer);
    EasyMock.verify(log);
  }

}

Looking at the name of the test, we should be able to safely assume that we expect the CustomerService to use the CustomerRepository for saving a new Customer. Going through the code of the test, it is apparent that we are testing one more scenario apart from the interaction between the CustomerService and the CustomerRepository: We expect the CustomerService to call the logCustomerSaved(customer) method on the AuditLog. In other words, we are also testing the interaction between the CustomerService and the AuditLog.

Let’s imagine that at some point the call to logCustomerSaved(customer) is removed from the actual CustomerService code. This will result to a breaking test telling us that CustomerService Should Save Customer Details With Repository is no longer happening. This is clearly not the case.

There is a sloppy way out of situations like the above and that is stubbing the code that needs to be there in order for the test to run. This can be achieved either by coding a Stub for the AuditLog or by employing the stubbing facilities offered by Mock Object Frameworks, such as EasyMock’s createNiceMock() method. This doesn’t significantly impove readability, neither does it solve the underlying problem which is the usual suspect behind dubious tests: The Application Code is probably not modeled correctly. In the CustomerService case, logging is probably not happening in the right place.

The benefits of code being responsible for performing one task are well documented and apply to both Application and Test Code. Breaking the one mock per test limit usually signifies that this rule is not sufficiently applied.

If you’d like to follow the discussion, feel free to grab The Testing Anti-Patterns Drafts feed.

Is the clutter in your test trying to tell you something?

Tuesday, November 14th, 2006

Tests are often the mirror of application code in terms of elegance and correct distribution of responsibilities. Stuart explains…

If you’d like to follow the discussion, feel free to grab The Testing Anti-Patterns Drafts feed.

The Testing Anti-Patterns Drafts (draft 4) : Buried Intent

Thursday, October 26th, 2006

Stuart on unreadable tests with convoluted expectations and unclear purpose.

The Testing Anti-Patterns Drafts (draft 3) : Testing a class with itself

Sunday, October 22nd, 2006

Among other interesting engineering marvels, cars tend to have an accelerator and a speed meter. It would obviously make sense to test both in order to verify whether they’re doing their job properly.

If a test consists of putting the pedal to the metal and watching the speed meter react, would that give us confidence that the accelerator works as intended? To an extend, it would, especially if the speed meter has had its own fair share of testing. However, if a couple of days down the line somebody worked on the speed meter to give it a stylish racing white panel and accidentally broke the way the meter displays speed, the accelerator test would erroneously indicate that the accelerator is broken.

This kind of danger is apparent when testing a class’s methods with other methods of the same class:

class Repository
  def save record
    OrmFramework.save record
  end

  def load id
    OrmFramework.load id
  end
end

class RepositoryTest < Test::Unit::TestCase
  def test_should_save_record
    record = Record.new
    repository = Repository.new
    repository.save record
    assert_equal record, Repository.load record.id
  end
end

If we changed the implementation of the load method, the test_should_save_record test would potentially break, although the save method still works as intended. A more sane test would look like:

def test_should_save_record
  record = Record.new
  Repository.new.save record
  assert_equal record, OrmFramework.load record.id
end

The important detail is that OrmFramework is an external import, whose implementation we know is not going to change and we can assume it has been tested to work as expected. The moral is to avoid testing code with code that has not been frozen and is still code in progress.

If you'd like to follow the discussion, feel free to grab The Testing Anti-Patterns Drafts feed.

The Testing Anti-Patterns Drafts (draft2)

Wednesday, October 4th, 2006

Stuart Caborn just delivered draft 2 of The Testing Anti-Pattern Drafts.

The Testing Anti-Patterns Drafts Vol. 1

Saturday, September 23rd, 2006

“The Testing Anti-Patterns Drafts” is a collaborative effort between Stuart “Stubs are evil” Caborn and myself, which aims to identify cases of Testing gone bad.

It consists of a single document that will undergo constant enhancements and modifications, in a “pair-authoring” manner, utilizing our respective weblogs as the platform.

We hope to get input from anyone following the document, our goal being to produce an interesting resource for the TDD, or Testing Oriented in general community.

Design Pervasive Testing

Both Stuart and I consider ourselves fortunate enough to work as members of teams where TDD is practiced by default.

There are two reasons beyond the obvious as to why I find it relatively harder to code in a non TDD approach. Test Driving my code enhances my vision on how to design/model/instrument my application’s universe. Also, starting with a test means work begins and ends with coding, not meetings, discussions or modeling our vision in pictures bound to be proven unrealistic when the first coding bottlenecks arise.

Having said that, testing properly is not easy. Past the simplistic examples, proper tests are hard work, often much harder than the actual code.

Encapsulation and Behavior are two of the most important characteristics of Object Oriented design. Applying them properly is difficult, and after all the hard work, testing Classes that are very concise about their behavior and very strict about what their peers can do with them, writing meaningful, readable, fine grained tests becomes a mission.

It’s the extra effort required that sometimes phases developers who end up taking shortcuts in order to facilitate testing.

Let’s look at an example:

public void testShouldProduceComplexObject() {
	ComplexObject expected = ObjectMother.getComplexObject();
	ComplexObject actual = classUnderTest.getComplexObject();
	assertEquals(expected, actual);
}

Obviously, such an assertion would only be valid if ComplexObject overrides the hashCode() and equals() methods. Countless times have I witnessed Classes implementing these two methods only to accommodate tests similar to the aforementioned example.

This is terminally wrong and a potential bug. Equality is an integral attribute of a Class’s behavior and should be strictly meaningful under the context of the Class’s definition.

I’m not aware of an easy way out of this sticky situation. Specific fields of the Class need to be tested for equality in isolation.

Does this mean that we need to expose all the Class fields we need to test by giving them public, or package level access? Not necessarily. In fact, not at all. After all, changing access levels would further compromise our Class’s behavior.

More and more, we have discovered Reflection to be an invaluable tool in our quest for less intrusive to purist OO design testing:

public void testShouldProduceComplexObject() {
	ComplexObject expected = ObjectMother.getComplexObject();
	ComplexObject actual = classUnderTest.getComplexObject();
	assertEquals(getPrivateField(expected, "fieldOne"),
		getPrivateField(actual, "fieldOne");
	assertEquals(getPrivateField(expected, "fieldTwo"),
		getPrivateField(actual, "fieldTwo");
	//etc...
}

If this were a container-bean type of Class with fifteen fields, that’s a lot typing we’d have to deal with. This is not necessarily bad for a Unit Test, but we could all do with less sore fingertips.

public void testShouldProduceComplexObject() {
	ComplexObject expected = ObjectMother.getComplexObject();
	ComplexObject actual = classUnderTest.getComplexObject();
	String[] fields = new String[] { "fieldOne", [...], "fieldFifteen" };
	for (String field : fields) {
		assertEquals(getPrivateField(expected, field),
			getPrivateField(actual, field);
	}
}

TBC…

If you’d like to follow the discussion, feel free to grab The Testing Anti-Patterns Drafts feed.