Add Zing to your unit tests
Introducing a framework for generic, productive, reliable, and maintenance-free unit tests
By Tanmay Ambre and Abhijeet Kesarkar, JavaWorld.com, 12/19/05
- Digg
- Reddit
- SlashDot
- Stumble
- del.icio.us
- Technorati
- dzone
Unit testing is as an integral part of extreme programming, and many open source tools and frameworks help developers write
unit tests. IDE plug-ins can create skeleton unit test cases, and Ant tasks and Maven goals automatically run test cases and
generate reports during continuous integration.
However, unit test cases are not generic. Any functional method handles multiple data scenarios. We write one test method
for every data scenario because we create the test data, fire the test, and validate the output in the same test method. If
a new requirement adds additional data scenarios for the method, then we end up writing more test methods. Thus, test-case
maintenance requires effort. The complexity of tests further increases when testing server-side components against data that
changes during transactions. In addition, we must ensure that the tests are always correct. All of these issues require considerable
time to address and increase the complexity of the test cases. Overall, we yearn for something that will remove the complications
involved in writing test cases and provide a generic set of test cases that are free from maintenance.
This article first outlines a comprehensive list of issues faced during unit testing and then details the creation of a testing
framework that facilitates the writing of generic and configurable unit test cases by integrating with multiple open source
testing tools and frameworks. In this article, we refer to the JUnit, JUnitPerf, Cactus, JUnitEE, and DbUnit frameworks and
tools such as Ant, CruiseControl, and XStream. Please note that this article is not a tutorial for these frameworks and tools.
Issues in unit testing
Here is the summary of the issues that must be addressed while unit testing:
- The effort required to create/maintain unit tests: We create test data within the test method's body. Thus, to have robust unit testing, we must create different test methods
for every possible combination of data for that functional method. Let's call combinations of data data scenarios. We do not generalize data creation and output assertion. Hence, we end up writing test methods for every data scenario that
needs testing, which causes maintenance issues. If we change the method to handle more data scenarios, we end up writing more
test methods. Also, changing the data for a scenario isn't always straightforward since the test data is embedded in the code
and we must change the test-case code and rebuild the entire test suite.
- Maintaining data consistency: We also need to maintain data consistency for the methods that complete database transactions. For example, if a method creates
a customer in the database and we try to create the same customer again, the unit test case will fail.
- Providing the same approach to writing unit tests but leveraging high-quality tools and frameworks: Some JUnit tools/frameworks available in the open source community enhance unit testing. One such tool is JUnitPerf. It allows
basic performance testing of the code. However, it has its own approach to creating test cases and running them. It needs
information about the load and response time to create tests. This information is hard-coded in the test methods and the developer
ends up writing more unit test cases. Abstracting that information out of the test case so the same unit test case can be
run as a load test or response-time test without the developer knowing the intricacies of JUnitPerf would prove beneficial.
- Complexity of test cases when testing server-side components: When testing server-side components, we need Java Enterprise Edition (JEE) features—e.g., JNDI (Java Naming and Directory
Interface) lookup and an EJB (Enterprise JavaBeans) container—which further adds to the complexity of test cases. Tools are
available for server-side testing, with the best examples being Cactus and JUnitEE. If we want to leverage the advantages
of both, we must glue them together and hide their configuration and intricacies from the developer. We must provide a simple
way for the developer to do server-side testing.
- Encouraging maximum test effectiveness (all the data scenarios are tested): Unit testing is a critical element of continuous integration. During continuous integration, we can use unit testing to measure
the build progress. That is, if the unit test reports show a 50-percent success rate, then we should be able to get an idea
of the overall build progress. To achieve such evaluation of build progress, the unit tests should be functionally correct
and reliable.
- Correct tracking of the build phase: Most unit test code follows the same pattern. On a higher level, the code looks repetitive. Abstracting such repetitive code
from the test cases minimizes the effort required to write unit test cases.
These issues can be resolved by writing a unit test framework that reduces testing effort, by making test cases generic and
configurable, and provides seamless integration with excellent open source unit test frameworks. The building blocks of the
framework are:
- Digg
- Reddit
- SlashDot
- Stumble
- del.icio.us
- Technorati
- dzone
Archived Discussions (Read only)