Sometimes, automation projects create the driver object in a setup() method that runs before each test class:
public class WebTest {
private WebDriver driver;
private static final String HOME_PAGE_URL = "https://www.vpl.ca/";
private static final String KEYWORD = "java";
private static final By SEARCH_BOX_ID = By.id("edit-search");
private static final By SEARCH_BUTTON_ID = By.id("edit-submit");
@BeforeClass
public void setUp() {
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
driver.manage().window().maximize();
}
@AfterClass
public void tearDown() {
driver.quit();
}
@Test
public void searchTest1() {
................
}
@Test
public void searchTest2() {
................
}
@Test
public void searchTest3() {
................
}
@Test
public void searchTest4() {
................
}
@Test
public void searchTest5() {
................
}
}
The driver object is declared at the class level, it is instantiated in the setup() method (that runs before any of the test scripts) and it is closed in the tearDown() method (that runs after all test scripts finished executing).
The reason for creating the driver (and opening the browser) before all the tests is easy to understand. The browser is opened before any test executes, then it is kept open and reused until all tests are done.
This leads to time savings because, in this scenario, we open the browser once and close it once:
setup() —> open browser
searchTest1 —> use browser
searchTest2 —> use the same browser
searchTest3 —> use the same browser
searchTest4 —> use the same browser
searchTest5 —> use the same browser
tearDown() —> close browser
If we would use the BeforeMethod annotation for the setup() method and AfterMethod annotation for the tearDown(), the browser would have to be started before each test and closed after each test:
setup() —> open browser for searchTest1
searchTest1 —> use fresh browser
tearDown() —> close browser for searchTest1
setup() —> open browser for searchTest2
searchTest2 —> use fresh browser
tearDown() —> close browser for searchTest2
setup() —> open browser for searchTest3
searchTest3 —> use fresh browser
tearDown() —> close browser for searchTest3
setup() —> open browser for searchTest4
searchTest4 —> use fresh browser
tearDown() —> close browser for searchTest4
setup() —> open browser for searchTest5
searchTest5 —> use fresh browser
tearDown() —> close browser for searchTest5
This is all great, right? Significant time savings!!!
Unfortunately, it is not great at all.
Why not, you may ask.
Because when the browser is not closed after each test, when the next test starts, it will use a browser that is not fresh, that already has cache and cookies accumulated.
Also, if the browser gets closed for some reason during the execution of the 1st test, the remaining tests will all fail.
And if the browser gets frozen during a test, all subsequent tests will fail too.
Creating the driver (and opening the browser) in a setup() method annotated with BeforeClass makes all tests dependent and sharing state. The second test depends on the browser used by the first test and “inherits” state from the first test. The third test depends on the browser used by the second test and “inherits” state from the first 2 tests.
The solution is simple.
Just use the BeforeMethod and AfterMethod annotations instead of BeforeClass and AfterClass. There are better methods of reducing the execution time than reusing the browser:
public class WebTest {
private WebDriver driver;
private static final String HOME_PAGE_URL = "https://www.vpl.ca/";
private static final String KEYWORD = "java";
private static final By SEARCH_BOX_ID = By.id("edit-search");
private static final By SEARCH_BUTTON_ID = By.id("edit-submit");
@BeforeMethod
public void setUp() {
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
driver.manage().window().maximize();
}
@AfterMethod
public void tearDown() {
driver.quit();
}
@Test
public void searchTest1() {
................
}
@Test
public void searchTest2() {
................
}
@Test
public void searchTest3() {
................
}
@Test
public void searchTest4() {
................
}
@Test
public void searchTest5() {
................
}
}