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 ;-)