M_Tech M_Tech - 17 days ago 5
Java Question

Best Way to Reset Browser State in TestNG with Selenium and Java

Can someone recommend the best way to 'tearDown' in the @AfterClass with testng? I occasionally get a hung window or popup and can't get back to the homepage to logout gracefully for the next class to start and avoid modal dialog errors.

I've tried getting a window handle on the homepage, then one on the popup, then putting a switchTo in my @AfterClass but it doesn't work. I've also tried driver.close(). But then my next class will be skipped with an unreachable browser error.

I really need a good tearDown @AfterClass method that can get out of whatever errors and popups are on page, and just leave a clean browser window at login page for the next test class to run.

Edit: Adding Code:

package TestPackage;

import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.Assert;
import org.testng.annotations.*;
import org.testng.annotations.Test;

//@Test (priority = 1)
public class test1 {
public static WebDriver driver = new FirefoxDriver();
Environment environment = Environment.QA03();
User testUser = User.ns_system();
AxUtilities axUtilities;

@BeforeClass
@Parameters("environment")
@Test
public void login(String environment1){

// environment = new Environment(environment1);
axUtilities = new DAxUtilities(environment1, driver);
// DAxUtilities dAxUtilities = new DAxUtilities(environment);
Login login = new Login();
login.getLogin(testUser, axUtilities, driver);
axUtilities.sleep(5000);
}

@Test
public void testNothing(){
String s = "public void testNothing() reached...";
System.out.println(s);
}


@AfterClass
public void verifyOKAndLogout() {

driver.quit();
// DAxUtilities dAxUtilities;

}

}


test class 1 and 2 are the same except for the class name...

And the tests are run from xml file. And I've tried many variants of the xml file, even putting each test in its own xml file:

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >

<suite name="TestSuite1" verbose="1">
<parameter name="environment" value="QA03"/>

<test name="Test1">
<classes>
<class name="TestPackage.test1"/>
<!--<class name="TestPackage.test2"/>-->
</classes>
</test>
<test name="Test2">
<classes>
<class name="TestPackage.test2"/>
</classes>
</test>

</suite>


But always two web drivers get created, one right after the other, at the very beginning of the test run, before any other code is executed. And breakpoints show the code is definitely skipping from the beginning of class 1, to the beginning of class 2, before running class 1 tests...

Answer

From what you wrote it seems that you are creating browser (instantiating WebDriver) before entire test suite and then execute all the tests using the same browser instance. Although it results with faster execution time it also introduces problems like the one you are having right now.

I would suggest creating a new instance of the browser before executing each test class (or even test method). In such case you can safely use driver.quit() in your @AfterClass method. Restarting browser every test will make your tests much more stable.

EDIT comments on your newly added code

  • the way you are instantiating WebDriver is not correct. If you have several test classes you will end up with multiple browser windows opened before any test is executed
  • you annotated one method with both @Test and @BeforeClass - this will cause the method to be executed twice in a row

The way it should (more or less) looks like is

public class MyTest {
   protected WebDriver driver;

   @BeforeClass   //I would even suggest to use @BeforeMethod but that's up to you
   public void setUp() {
      driver = new FirefoxDriver();
      //other instantiations and assignments if necessary
   }

   @Test
   public void login() {
      driver.get("http://watever.com");
      //do whatever
   }

   @Test
   public void someOtherTest() {
      //do something else
   }

   @AfterClass   //or @AfterMethod
   public void tearDown() {
      driver.quit();
   }
}
Comments