A while back I started working on a project in the evenings that turned in to MyThingo. I decided from the get go to make sure I built exhaustive unit tests for the codebase. At the beginning I was using JUnit but I had read about TestNG a few times so I decided to give it a try. It was an amazingly fast transition. If you want to give it a try, just follow the documentation that comes with it.
After I started using it the little things that it does better are what kept me using it. Here are a few of the things that I use a lot:
Annotation Based Configuration
Rather than having to use a naming convention or extending a particular TestCase I can just mark a method as testable. I don’t need to have all my methods start with “test”. That gets annoying. Here’s an example of how it looks:
@Test public void verifyAddition { assert 4 == Number.add(2,2) : "2 + 2 should have added up to 4"; }
Obviously the unit test above is not real but it shows how you mark a test method and that you don’t have to name it testVerifyAddition. The class this method is in is just a standard POJO as well.
Another annotation that comes in really handy is the ExpectedExceptions annotation. This tells TestNG that the method should fail unless it receives an exception of the specified type. Here’s the difference between the normal way of testing for a particular exception in JUnit and one in TestNG. First, the JUnit way:
public void testForNullArgumentException() { try { new Foo.doMethod(null); fail("I should have received a NullArgumentException"); } catch(NullArgumentException e) { return; } }
Now the way it’s done in TestNG:
@Test @ExpectedExceptions(NullArgumentException.class) public void nullArgInMethodX { new Foo().doMethod(null); }
A little simpler, heh? None of what I’ve shown is impossible in JUnit (obviously) but overall it just makes testing easier. And the key to getting folks to unit test is to make it as painless as possible.
More Flexible Execution Profiles
One of the areas of JUnit that can drive a person crazy is that the class is dumped and loaded for every test. That means you have to setup and tear down after every test method. The idea is that you start with a clean slate for every test. But in the real world that’s not always ideal nor is it performant. Sometimes I just want to initialize items for the entire test class and other things for every method. TestNG lets you do this.
The way you do this is with the @Configuration annotation. This annotation can be added to methods and then its options allow to specify how the annotation affects the test class. For example, the beforeTestMethod parameter tells TestNG that the method should be run before each test method in the class. With beforeTestClass the method should be executed once at the beginning of the test run for this class. There are other options you can find in the TestNG documentation but these are the ones I use the most.
The last item I thought I’d go over is the ability to tell TestNG that a method X depends on the successful execution of other method(s) and if the dependent method(s) fails then there is no use in executing the test method in question. This can cut down on additional test execution times.
One of the issues I’ve had in getting other developers to unit test is that it’s usually just a pain to do tests beyond simple unit testing. You have to face facts that some developers just don’t care about it as much as you do. The key is making it as painless as possible and to make it relatively easy to mimic the environment that the code is going to run in. I’ve covered some of the areas where TestNG helps accomplish the simple/easier/faster part and in a future post I’ll cover some of the other areas such as setting up your Spring environment in conjunction with Hibernate using Hypersonic and auto-created database schemas using in-memory database. Another topic will be the use of easy mock for testing features that would normally require a container such as Tomcat. If you’re interested in those, leave me a comment or shoot me an e-mail and I’ll let you know when those are up and ready.
Glad you like TestNG, Mike. Feel free to send suggestions / bug reports to the testng-users mailing-list…
—
Cedric