Cosmopolitan fixtures in TestNG

As I’ve written about before, TestNG supports parametric testing quite copaseticly; in fact, not only can you obtain parameters for tests, but TestNG also supports parametric fixtures. This means you can effectively create generic fixture objects that tailor themselves to particular environments.

For example, because it’s my bag, I often find myself needing a hip DbUnit fixture to handle managing a state of a database during testing; however, in order for DbUnit to work, at a minimum, you must provide:

  • a database driver to load
  • a connection URL
  • the database user
  • the database password
  • a path to a seed file

DbUnit uses the first 4 aspects to connect to a database, which it’ll seed with the contents found in item #5. These 5 items are often hard coded in testing scenarios; however, with TestNG’s smokin’ parametric fixtures, you can force the actual values to be defined at test time by placing them into TestNG’s testng.xml file.

First I can define a cosmopolitan DbUnit fixture like so:

public class DatabaseFixture {

 @Parameters({"seed-path","db-driver","db-url","db-user","db-psswrd"})
 @BeforeTest
 public void seedDatabase(String seedpath, String driver,
   String url, String user, String pssword) throws Exception {
  IDatabaseConnection conn =
     this.getConnection(driver, url, user, pssword);
  IDataSet data = this.getDataSet(seedpath);
  try {
   DatabaseOperation.CLEAN_INSERT.execute(conn, data);
  }finally {
   conn.close();
 }
}

private IDataSet getDataSet(String path) throws IOException,
 DataSetException {
  return new FlatXmlDataSet(new File(path));
}

private IDatabaseConnection getConnection(String driver, String url,
  String user, String pssword ) throws ClassNotFoundException,
   SQLException {
  Class.forName(driver);
  Connection jdbcConnection =
   DriverManager.getConnection(url, user, pssword);
  return new DatabaseConnection(jdbcConnection);
 }
}

Note how the tripping 5 items listed earlier are now parameters to this fixture via the Parameters annotation, which decorates the seedDatabase method. Wiring actual values to these parameters is done via the parameter element, which can be placed in TestNG’s testng.xml file as follows:

<suite name="Acceptance Tests">

 <parameter name="seed-path" value="test/conf/seed.xml"/>
 <parameter name="db-driver" value="org.hsqldb.jdbcDriver"/>
 <parameter name="db-url" value="jdbc:hsqldb:hsql://127.0.0.1"/>
 <parameter name="db-user" value="foo"/>
 <parameter name="db-psswrd" value="bar"/>

 <test name="CRUDs" >
  <packages>
   <package name="test.org.acme.web" />
   <package name="test.org.acme.web.fixtures" />
  </packages>
 </test>
</suite>

With these parameters defined in TestNG’s configuration file, I can now vary their values at runtime for different environments by defining different test groups within the testng.xml file– or, I can even use Ant’s replace task to replace these values with environment specific values. Either way, using TestNG’s parametric fixtures is a sure fire way to create generic fixtures that can be reused in different scenarios easily, man! Dig it?

Related odds and ends
 

3 Responses to “Cosmopolitan fixtures in TestNG”

  1. on 14 Mar 2007 at 12:33 am Andres Almiray

    Andy, besides the hip solution you’ve presented for DbUnit there is also the alternative of using an IDatabaseTester impl, like PropertiesBasedDatabaseTester, which will pull its configuration from System.properties.

    Regardless of it, it is good to know how to do parametric testing with TestNG, thanks!

  2. on 14 Mar 2007 at 2:16 am Andy

    Great point, Andres!! Thank you!! I was hoping you’d comment as I know your involvement with DbUnit– keep up the great work!!


  3. [...] Original post by Andy [...]

Trackback this Post | Feed on comments to this Post

Leave a Reply