views:

19

answers:

2

In using TestNG for my Selenium framework, the setUp method is relatively complex. There are multiple points that it can break and I would like to split it into separate steps.

Ideally it would look something like this:

// Does some DB stuff, logs some messages
@BeforeMethod(alwaysRun = true)
preTestCase


// Instantiates and opens up Selenium
@BeforeMethod(dependsOnMethods = {"preTestCase"})
seleniumSetup


// Closes Selenium only if it was properly setup
@AfterMethod(dependsOnMethods = {"seleniumSetup"})
seleniumTearDown


// All other test case teardown, error logging
@AfterMethod(alwaysRun=true)
postTestCase

What I want to avoid is failing in preTestCase due to a DB issue and then getting a secondary failure due to seleniumTearDown trying to close a non-existent instance. In that situation, only postTestCase should be run. I am getting this error: seleniumTearDown() is not allowed to depend on public void seleniumSetUp(org.testng.ITestContext). Is this not allowed / bad design? How do I enforce run-order between the two tearDown methods so that postTestCase() is always run last, regardless of if seleniumTearDown is run?

+1  A: 

Your model seems a little washy, Setup and Teardown shouldn't fail. Although they could possibly no-op. As in; "Attempted to make a db connection, wasn't available so did nothing instead" then in tear down you should check if their is a connection before attempting to close it.

Otherwise if you want to maintain your current model you could use some sort of manual check instead of the annotation (a boolean or a singleton class would work).

In Setup:
if(dbGetConnected()) {
....
} else {
  dbisntconnected = true;
}

In tearDown:
if(!dbisntconnected) {
    dbClose();
}
Valchris
This is a simplified example. The purpose of this is to avoid using manual checks and increase the granularity of failures by leveraging TestNG's built in tools.
dhackner
+1  A: 

The error you are seeing is because you are trying to have an @AfterMethod depend on a @BeforeMethod, which doesn't make sense. You can have configuration methods depend on each other, but they need to be all of the same type (e.g. all @AfterMethod or all @BeforeMethod).

As for your other problem, the solution given by Valchris is what I recommend. If you know your tests or configurations are fragile but they shouldn't interrupt the test run, catch the exception yourself so that TestNG will never see it.

Cedric Beust
It's not that the setUp method shouldn't interrupt the test run, in fact a run failure is desired in this example. What I want to avoid is setUp 1 of 2 failing and then having tearDown throw a second error because it is trying to tearDown the setUp part that never ran, thus the notion of pairing setUps and tearDowns. I'll go with the manual solution. Thanks to both of you for the quick answers!
dhackner