Monday, June 8, 2009

Modernizing MultithreadedTC: JUnit 4 integration

MultithreadedTC is a nice library to help writing tests for multi threaded applications (go check out their website for some examples, I can 't explain it better). Writing and testing multi threaded applications is not an easy task, so having a decent test suite for to help with that task is no luxury at all. I think MultithreadedTC does a nice job, it certainly helped me to write better and more elegant tests than I would have been able to without the library.

One thing I find it a bit frustrating though, is that it doesn't integrate with JUnit (4) very nicely. Basically, with MultithreadedTC, you have to write a class which extends MultithreadedTestCase, with some methods that start with "thread" (a naming convention for MultithreadedTC to know what to run in which threads)
class MyMultithreadedTest extends MultithreadedTestCase {
  public void threadFoo() {
    ...
  }
}
To execute this "multi threaded test case", you have to instantiate it and pass it on to one of the static methods in the TestFramework
TestFramework.runOnce(new MyMultithreadedTest());
Although the name MultithreadedTestCase suggests it is a JUnit test, it is not. To get it all bootstrapped in a JUnit test, you typically end up with an inner class (extending MultithreadedTestCase) inside a JUnit test, and a single JUnit test method to call the TestFramework.runOnce() method
public class SomeTest {
  class MyMultithreadedTest extends MultithreadedTestCase {
    public void threadFoo() {
      ...
    }

    ...
  }
  
  @Test
  public void test() {
    TestFramework.runOnce(new MyMultithreadedTest());
  }
}
This obviously works, but I think we can do better.

I updated the MultithreadedTC library such that multi threaded tests are real JUnit tests (including all the benefits that has, such as using the @After and @Before annotations), in stead of merely something which can be bootstrapped from within JUnit. I also added some annotations for the "thread" methods, in stead of the naming conventions.

The above now looks like this
public class SomeTest {

  @Thread("Foo")
  public void threadFoo() {
    ...
  }
  
  @Test
  public void test() {
    ...
  }
}
Consider the first example on the authors website for a more complete example. This can now be written like this:
public class MTCCompareAndSetTest extends MultithreadedTestCase
{

    AtomicInteger ai;

    @Before
    public void initialize()
    {
        ai = new AtomicInteger(1);
    }

    @Threaded
    public void getTwoSetThree()
    {
        while (!ai.compareAndSet(2, 3)) Thread.yield();
    }

    @Threaded
    public void getOneSetTwo()
    {
        assertTrue(ai.compareAndSet(1, 2));
    }

    @Test
    public void resultShouldBeThree()
    {
        assertEquals(ai.get(), 3);
    }
}
Advantages of this approach include: no inner classes, no explicit TestFramework.runOnce() method calls, usage of standard JUnit annotations, test class is a JUnit class, annotations in stead of naming conventions, ...

Let me know if you are interested in a tgz file which contains the code of this modified MultithreadedTC library. It also contains all the tests of the original sourcecode, adapted to the more modern version.

I have tried to contact the authors of MultithreadedTC, asking them if they are interested. I am willing to share my modifications with them to get them included in the MultithreadedTC library, but I'm still awaiting their reply. Maybe they are deadlocked ;-)

7 comments:

Martin said...

This is exactly what I was looking for!

I would like to request your modifications, maybe you could put them on github or someplace else.

I also wrote you through launchpad.net, sorry for the inconvenience.

Yours,
Martin Schuerrer
martin@schuerrer.org

Jan Van Besien said...

@Martin

I created a google code project: http://code.google.com/p/multithreadedtc-junit4/

This contains the source of the multithreadedTC project itself + my JUnit 4 enhancements.

I would prefer my enhancements to make it into the multithreadedTC library itself, but I have never received an answer on my mail to the authors. I filed an issue on their google code project to ask for it again.

Martin said...

Great! Thank you!

As you said, the developers of multithreadedtc appear unresponsive, do you have any plans for continuing development or releasing your own version in a maven repository?

Thanks again!
Martin

Jan Van Besien said...

I didn't really have any plans, but if people seem to be interested... I might invest some time in it in the future (can't really promise anything right now).

Don't hesitate to make patches or other enhancements yourself. I'll certainly look into them and include them in the google code project.

Martin said...

Ok I might just do that :)

Anyways, am I right to assume you put your modifications under the original BSD license?

Dennis said...

I would like to see if this will work for jUnit testing my dB connection manager code which is multi-threaded. I went to the code.google.com link but there are no downloads available for your code changes. Are you now merged with MultithreadedTC?

Dennis said...

Please disregard. I found the svn link for read only.