Friday, March 18, 2011

Detecting Concurrency Problems using TestNG

With the emphasis on product quality, unit and integration testing is gaining widespread momemtum, and TestNG seems to have become the defacto standard for writing these tests. A great feature in TestNG - that is often missed in all the JUnit vs. TestNG comparisons on the web - is the ability to execute a test in parallel using multiple threads. This feature is pretty useful in detecting concurrency problems in the code. A developer could write a test at the Controller level that executes the Service and DAO (Data Access Object) code, and if this code contains any concurrency constructs for thread-safe access, then the TestNG threads will detect concurrency problems such as race conditions and deadlocks.

Using the TestNG framework, it is relatively easy to specify that a given test be executed in parallel. This can be done using additional parameters to the @Test annotation.

As an example, consider the following test:

@Test (threadPoolSize = 3, invocationCount = 9, timeOut = 1000)
public void myTest() {
// write your test here
}

The threadPoolSize determines the number of threads that are used to execute the tests, and the invocationCount determines the total number of times that the test is executed. The timeOut parameter - 1 second in the above example - guarantees that none of the threads will block on the others, in effect avoiding a deadlock. However, this is not something that a developer should try to avoid, because if there is a deadlock, it is better to detect it sooner that later. Therefore, in general, it is better of omit the timeOut parameter.

With the advent of these super-easy testing frameworks and the value-proposition that they bring, most developers are jumping on the unit/integration testing bandwagon. This is great for the software engineering field in general, as eventually some day bugs will not be considered as the norm in a software product.