A blog about software development and other software related matters

Blog Archive

Tuesday, December 4, 2007

Taking back control on your tests with TestNG

I'm truly a testing fanatic, in fact i think that for each component coded tests should be an integral part the process.
The thing is that as your code grows it gets harder to maintain the tests that you've written in addition JUnit adds pain to misery due to its bad design.
Its true that latest 4.* versions had fixed some really annoying practices like the naming convention of test methods and the need to extend a test base class but still it lacks in many other areas.

One of the major problems in JUnit is the fact that the main grouping point of tests is the test class itself which isn't fined grained enough, TestNG on the other hand allows to include any test method within any group no matter in which class its defined, for example:


package tests;

public class SomeCases {

@BeforeMethod(groups = {"restore", "authorization"})
public void cleanup() {
// some common cleanup code
}

@Test(groups = {"restore"})
public void getSingleModel() {
// ..
}

@Test(groups = {"restore"})
public void getManyModels() {
// ..
}

@Test(groups = {"authorization"})
public void authorizationService() {
// ..
}
}

This class holds a bunch of test methods which are divided to two major groups restore and authorization, this fine grained division enables all sorts of new possibilities like the handling of cross cutting concerns such as the cleanup method (we could easily move it to a super class to enable it on multiple classes).

Another possibility is to mix and match test suites that include test methods scattered around many classes, for example the next test method which belongs to the restore group that we've seen above:

package tests;

public class MoreSomeCases {
@Test(groups = {"restore"})
public void validateModelRestore() {
// ..
}
}

is made executable (with all the other restore methods) by defining the following suite (XML):

⟨suite name="BASIC_FUNCTIONALITY" verbose="1"⟩
⟨test name="BASIC_FUNCTIONALITY"⟩
⟨groups⟩
⟨run⟩
⟨include name="restore"/⟩
⟨/run⟩
⟨/groups⟩
⟨packages⟩
⟨package name="tests"/⟩
⟨/packages⟩
⟨/test⟩
⟨/suite⟩

this will enable the running of all the restore methods no matter in which class they are defined (this is an easy way to run integration tests).

TestNG has a lot more to offer (only a partial list):
- Defining input parameters of test methods and injecting them with data providers.
- Defining dependencies among tests and groups.
- Run tests in parallel.

Head on and check it out!

No comments: