Hunting test fixture leaks

Global state is unwanted in a system for many reasons. One of these reasons is that it makes testing difficult due to side effects that can easily leak from one test and affect others randomly.

However, having no global state is easier said than done, and I am yet to see an enterprise system that does not rely on any. When global state does infiltrate in your system, you want to at least ensure that the tests stay clear of the consequences.

First, you might want to introduce mocking so that at least you can control what is being returned by the global object. Let's suppose you initialize this mock with a initializeGlobalMock method. Once you have the method, you can easily call it from the setup of your tests and have the tests isolated from others.

However, to leave the system in a clean state, you would still need to release the global mock at the end of your test. Without this, you might end up having random test errors. Thus, every time you use a mock, you want to ensure that at the end of the test you are resetting it.

This can easily be tested statically. For example, if you have a Java system and you use JUnit 4, you can use the below Moose script:

model allModelClasses select: [:each |
  setUp := each methods anySatisfy: [:m |
   (m isAnnotatedWith: 'Before') and: [
     m invokedMethods anySatisfy: [ :provider | 
      provider name = 'initializeGlobalMock' ] ] ].
  tearDown := each methods anySatisfy: [:m |
   (m isAnnotatedWith: 'After') and: [
     m invokedMethods anySatisfy: [ :provider | 
      provider name = 'resetGlobalMock' ] ] ].
  setUp and: [tearDown not] ]

While not ideal, you can still manage the situation with a checker that is cheap and can be integrated easily in the continuous integration process.

Posted by Tudor Girba at 1 July 2013, 9:46 pm with tags analysis, moose link
|