When getting started with Selenium automation in Java, some testers write code like this:
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.Test;
public class Tests {
static WebDriver driver;
public Tests() {
driver = new ChromeDriver();
driver.manage().window().maximize();
}
public static void main(String[] args) {
searchReturnsResults();
goToLoginPage();
}
public static void searchReturnsResults() {
driver.get("https://www.example.com");
WebElement searchBox = driver.findElement(By.id("searchBoxId"));
searchBox.sendKeys("java");
WebElement searchButton = driver.findElement(By.id("searchButtonId"));
searchButton.click();
assertTrue(driver.getCurrentUrl().contains("/results"));
}
public static void goToLoginPage() {
driver.get("https://www.example.com");
WebElement loginLink = driver.findElement(By.id("loginLinkId"));
loginLink.click();
assertTrue(driver.getCurrentUrl().contains("/login"));
}
}
The project is created as a standalone application with a main method.
The main method runs the 2 tests.
The tests are using a static driver that is created in the class constructor. The browser is then started once before the first test and reused by the second test.
Each test is implemented in a separate method.
Running the main method will run the 2 tests.
Not bad, isn’t it?
If this is how you write your code, you should stop right away.
Why should you not write code like this?
There are multiple problem with this code.
after the main method finishes executing, there is no evidence anywhere about the tests passing or failing; you could modify the tests by adding some logging code at the end of each method
if the first test fails due to an exception, the second test is not executed
if the first test passes, the second test does not run in a clean browser; the browser retains all the cookies and cache that are created by the first test
there is no code that closes the browser after the second test ends
both tests run in the same browser
all test methods are created as static
the tests run always in the same order
This is a very inefficient way of writing your Selenium code.
However, the correct solution is very simple.
Create a new project
Add the TestNG library to it
Create a class that does not have a main method
Modify the code as follows:
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.Test;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.AfterMethod;
public class Tests {
private WebDriver driver;
@BeforeMethod
public void setUp() {
driver = new ChromeDriver();
driver.manage().window().maximize();
}
@AfterMethod
public void tearDown() {
driver.quit();
}
@Test
public void searchReturnsResultsTest() {
driver.get("https://www.example.com");
WebElement searchBox = driver.findElement(By.id("searchBoxId"));
searchBox.sendKeys("java");
WebElement searchButton = driver.findElement(By.id("searchButtonId"));
searchButton.click();
assertTrue(driver.getCurrentUrl().contains("/results"));
}
@Test
public void goToLoginPageTest() {
driver.get("https://www.example.com");
WebElement loginLink = driver.findElement(By.id("loginLinkBoxId"));
loginLink.click();
assertTrue(driver.getCurrentUrl().contains("/login"));
}
}
The main() method is removed so we ca rely 100% on the unit test framework, TestNG in this example.
Doing this improves the code in many ways:
the driver is created in the setUp() method; since this method is annotated with @BeforeMethod, it is executed automatically before any test
the driver is closed in the tearDown() method; since this method is annotated with @AfterMethod, it is executed automatically after each test
using the setUp() and tearDown() methods means that the driver is created before and closed after each test; this means that each test uses its own clean browser
each test method is annotated with @Test; because of this, after running all tests, the test status will be displayed in the TestNG plugin window
since each test has the @Test annotation, they will run independently and in a random order
if any of the tests fails due to an exception, the other test is not impacted
the driver is no longer static
You do not need a main() method in your Selenium project.
Instead, rely 100% on your unit testing library.