10
Unit testing concurrent code

Unit testing concurrent code

Embed Size (px)

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.

Citation preview

Page 1: Unit testing concurrent code

Unit testingconcurrent code

Page 2: Unit testing concurrent 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

Page 3: Unit testing concurrent code

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

JUnit

Page 4: Unit testing concurrent code

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

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

TestNG

Page 5: Unit testing concurrent code

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

Page 6: Unit testing concurrent code

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

Page 7: Unit testing concurrent code

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)

Page 8: Unit testing concurrent code

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}

Page 9: Unit testing concurrent code

@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; }

Page 10: Unit testing concurrent code

http://rafael.codes@rafaelcodes

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

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