dhackner
dhackner

Reputation: 3050

Multiple levels of setUp/tearDown in TestNG?

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?

Upvotes: 2

Views: 6192

Answers (2)

Cedric Beust
Cedric Beust

Reputation: 15608

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.

Upvotes: 2

Valchris
Valchris

Reputation: 1481

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();
}

Upvotes: 2

Related Questions