Desktop Java

More Units with MoreUnit

Just over a year ago I wrote a post about working with JUnit in Eclipse. One of the commenters recommended MoreUnit in order to increase testing efficiency even more. Giving it a try I was delighted and the plugin’s keyboard shortcuts were immediately memorized by my autonomic nervous system…

Additionally after using MoreUnit for a while I recognized a slight but notable change in one of my working routines. More precisely it seems that I tend to extract more classes covered by own unit tests during refactorings1 than I did before. As maintaining cohesion results in many small classes2 this is probably a good thing.

Well, one could say ‘MoreUnit, the name says it all’ but as I did not expect it to be meant in that way, I decided this might be a good subject for a post. So let’s have a look at the following example to get started:

class ActionItem extends MouseAdapter  {

  private Label control;
  private Runnable action;
  private boolean mouseDown;

  [...]

  ActionItem( Composite parent, Runnable action ) {
    this.control = new Label( parent, SWT.NONE );
    this.control.addMouseListener( this );
    this.action = action;
  }

  @Override
  public void mouseDown( MouseEvent event ) {
    markMouseDown();
  }

  @Override
  public void mouseUp( MouseEvent event ) {
    handleMouseUp( event );
  }

  private void markMouseDown() {
    mouseDown = true;
  }

  private void handleMouseUp( MouseEvent event ) {
    if( mouseDown && inRange( event ) ) {
      action.run();
    }
    mouseDown = false;
  }

  private static boolean inRange( MouseEvent event ) {
    Point size = ( ( Control )event.widget).getSize();
    return    event.x >= 0 && event.x <= size.x 
           && event.y >= 0 && event.y <= size.y;
  }

  [...]
}

The class is an excerpt of a custom UI control3 and it shows how such a control could implement mouse click behavior. We proceed on the assumption that we have an appropriate unit test case with sufficient coverage up and running. It is also safe to presume that several structural refactoring steps have already taken place before reaching the arrangement of the code snippet above.

Considering the mouse click as a single responsibility it is arguable that it should be separated into its own class. To do so I generally start with an inner class where I move the related methods and fields to. After that I assign an instance of that new type to a new field of the surrounding class as demonstrated in the ActionItem constructor below. Last but not least I fix the now undefined method calls by delegating those calls to the newly created field4:

class ActionItem extends MouseAdapter  {

  private Label control;
  private ClickHandler clickHandler;

  [...]

  ActionItem( Composite parent, Runnable action ) {
    this.control = new Label( parent, SWT.NONE );
    this.clickHandler = new ClickHandler( action );
    this.control.addMouseListener( this );
  }

  @Override
  public void mouseDown( MouseEvent event ) {
    clickHandler.markMouseDown();
  }

  @Override
  public void mouseUp( MouseEvent event ) {
    clickHandler.handleMouseUp( event );
  }

  static class ClickHandler {

    private Runnable action;
    private boolean mouseDown;

    ClickHandler( Runnable action ) {
      this.action = action;
    }

    private void markMouseDown() { [...] }
    private void handleMouseUp( MouseEvent event ) { [...] }
    private static boolean inRange( MouseEvent event ) { [...] }
  }

  [...]

}

By running the ActionItem‘s test case successfully and checking the coverage once again, one can be pretty sure that the extraction described above did not introduce any mistakes. Because of this it feels fairly save to move the ClickHandler finally to its own file.

However now there is a class serving as some kind of ‘subcomponent’ which is only covered indirectly by the ‘main’ component’s test case. I have made the observation that such classes often develop a living of their own. Meaning their functionality expands or they are getting reused by other classes or both. At some point in time it probably gets rather difficult to add meaningful and/or comprehensible tests. This is becauce the test class itself lacks the cohesion which was introduced to the unit under test by splitting it into two.

For that reason I usually create a particular test case for the extracted class right away. Even more as with MoreUnit available this can be achieved quite intuitively, actually providing the new test case automatically with a basic set of test method stubs. Continuing our example we would open the extracted ClickHandler in an editor, press ‘ctrl+j’ 5 and select in the upcomming wizard for which method we would like to have a stub created:

new-test

Pressing finish creates a test case correctly located under the according test source folder of your project 6 that looks – depending on your MoreUnit settings – somewhat like this:

public class ClickHandlerTest {

  @Test
  public void testMarkMouseDown() {
    fail( "Not yet implemented" );
  }

  @Test
  public void testHandleMouseUp() {
    fail( "Not yet implemented" );
  }
}

The stubs may serve as starting point for populating the test case meaningfully from scratch. But mind that there is already a full coverage providing set of tests in the ActionItemTest available. So another possibility is to move the content of the mouse click related tests to the newly created ClickHandlerTest. While the latter now does the thorough testing of the new unit, care has to be taken that there are enough tests left in the ActionItemTest that ensures a proper integration of the ClickHandler7.

Conclusion

Working like this for some time now, I am under the impression that maintainability and further development of my code (including test cases) gradually improves. It can be said of course, that MoreUnit should not be the cruicial factor to decide whether or not to extract a certain responsibility into its own class. But to me it seems it eases the decision to do so, by helping to overcome one’s weaker self, having an appropriate test case for the new class just a few clicks away.

  1. See red/green/refactor mantra of Test Driven Development
  2. Robert C. Martin, Clean Code, Chapter 10: Classes
  3. Although the example has been inspired by my current work I stripped it down to the bare minimum needed for this post
  4. A further refactoring step might be to change the ClickHandler in a way that it extends MouseAdapter or implements MouseListener. After that the click handler itself could be registered as mouse listener at the label replacing the action item. This would eliminate the delegating mouse handler methods in ActionItem completely. However I omit this step here to keep the post in scope
  5. This shortcut is usually used to switch between units under test and their according test cases. As you get used to this quite fast, it somehow serves even more as a ‘missing test reminder’ than the particular decorators do…
  6. With OSGi based systems this also might be a test fragment
  7. Note that the extraction process simplifies the test set up of the mouse click functionality tests. The extracted class has no dependency to a SWT widget derivative in the constructor, which allows to provide e.g. a test set up based on mocks. The latter is not possible without fuss for the ActionItem and therefore setup/teardown methods are needed to create, initialize and dispose of Display/Shell instances for example

 

Reference: More Units with MoreUnit from our JCG partner Frank Appel at the Code Affine blog.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
mehar
mehar
10 years ago

Nice Thread :)

Back to top button