Unit testing concurrent code

Post on 02-Feb-2015

353 views 2 download

description

Concurrency has become an increasingly important topic in the Java space. Nevertheless, most Java developers do not address concurrency in their unit tests. This talk shows how to and how not to test concurrent code and introduces Thread Weaver, a library for testing concurrent code.

Transcript of Unit testing concurrent code

Unit testingconcurrent code

public class FlawedList<T> extends ArrayList<T> { public boolean putIfAbsent(T object) { boolean absent = !super.contains(object); if (absent) { super.add(object); } return absent; }}

Implementing a broken unique list

@Testpublic void testPutIfAbsent() { FlawedList<String> list = new FlawedList<String>(); list.putIfAbsent("foo"); list.putIfAbsent("foo"); assertThat(list.size(), is(1)); }

JUnit

FlawedList<String> list = new FlawedList<String>();

@Test(threadPoolSize = 5, invocationCount = 20) public void testList() { list.putIfAbsent("foo"); assertThat(list.size(), is(1)); }

TestNG

TestNG with breakpoints

public class FlawedList<T> extends ArrayList<T> { public boolean putIfAbsent(T object) { boolean absent = !super.contains(object); if (absent) { super.add(object); } return absent; }}

FlawedList<String> list = new FlawedList<String>();

@Test(threadPoolSize = 5, invocationCount = 20) public void testList() { list.putIfAbsent("foo"); assertThat(list.size(), is(1)); }

public boolean putIfAbsent(T object) { boolean absent = !super.contains(object); if (absent) { super.add(object); } return absent; }

Testing with break points: first weaving

FlawedList["foo", "foo"]FlawedList["foo"]FlawedList[]

Testing with break points: second weaving

Thread 1Thread 2

Legend:

ThreadWeaver

absent

true

falsetrue

public class WeavedFlawedListTest { private FlawedList<String> list;

@ThreadedBefore public void before() { list = new FlawedList<String>(); }

@ThreadedMain public void mainThread() { list.putIfAbsent("foo"); } @ThreadedSecondary public void secondThread() { list.putIfAbsent("foo"); }

@ThreadedAfter public void after() { assertEquals(1, list.size()); } }

ThreadWeaver (https://code.google.com/p/thread-weaver)

Seamless JUnit integration

public class MyListTest {

@Test public void testFlawedList() { AnnotatedTestRunner runner = new AnnotatedTestRunner(); runner.runTests(getClass(), FlawedList.class); }

// put method with @Threaded<...> annotations here}

@Test public void testFlawedList() { AnnotatedTestRunner runner = new AnnotatedTestRunner(); runner.runTests(getClass(), FlawedList.class); }

How does it work?

Instrumented code:

public boolean putIfAbsent(T object) { Framework.considerBreakpoint(Thread.currentThread(), 0); boolean absent = !super.contains(object); Framework.considerBreakpoint(Thread.currentThread(), 1); if (absent) { Framework.considerBreakpoint(Thread.currentThread(), 2); super.add(object); } Framework.considerBreakpoint(Thread.currentThread(), 3); return absent; }

http://rafael.codes@rafaelcodes

http://www.kantega.nohttp://blogg.kantega.no

http://bytebuddy.nethttps://github.com/raphw/byte-buddy