Running tests against multiple browsers
One of the advantages of Selenium Web Driver is possibility to running tests in different types of browsers. It is not rare situation that we want to run all our tests on all browsers supported by the tested application. We usually want to have possibility to run those tests from IDE only on one defined browser. In this article I will describe how to create your selenium web driver framework to be able to run all your tests from maven on different browsers and on default browser directly from IntelliJ Idea. To do that we will use maven, java and TestNG.
To complete our task we have to create xml configuration file in which we create suite that contains list of test classes to run per browser. In my case I am adding two same classes (DoorsListTest, CreateUserTest) to be run twice - once with parameter browser=chrome and second with browser=firefox. It reflects situation that I want to run my tests on Chrome and Firefox.
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" > <suite name="Jenkins: E2E Test - DEV"> <test name="ChromeTest"> <parameter name="browser" value="chrome"/> <classes> <class name="com.assaabloy.shared.figaro.monitoring.DoorsListTest"/> <class name="com.assaabloy.shared.figaro.users.CreateUserTest"/> </classes> </test> <test name="FirefoxTest"> <parameter name="browser" value="firefox"/> <classes> <class name="com.assaabloy.shared.figaro.monitoring.DoorsListTest"/> <class name="com.assaabloy.shared.figaro.users.CreateUserTest"/> </classes> </test> </suite>
Next I am adding new profile to pom.xml which is responsible for running all tests from previously created configuration file.
<profiles> <profile> <id>all-browsers-remote</id> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <suiteXmlFiles> <suiteXmlFile>test-suites/all-browsers-remote.xml</suiteXmlFile> </suiteXmlFiles> <goal>test</goal> </configuration> </plugin> </plugins> </build> </profile> </profiles>
To make this working as expected we have to add a few files to our framework. The first one is enum BrowserType which contains all browsers on which we are able to run our tests.
package com.testcraftsmanship.model.config; public enum BrowserType { CHROME, FIREFOX, CHROME_HEADLESS }
Next important class is the DriverFactory which creates the WebDriver instance depending on what browser type we pass as an argument.
package com.testcraftsmanship.model.config; import com.testcraftsmanship.model.base.BaseTest; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.chrome.ChromeOptions; import org.openqa.selenium.firefox.FirefoxDriver; public class DriverFactory { private static final String CHROME_DRIVER_LOCATION_PROPERTY = "webdriver.chrome.driver"; private static final String FIREFOX_DRIVER_LOCATION_PROPERTY = "webdriver.gecko.driver"; private static final BrowserType DEFAULT_BROWSER_TYPE = BrowserType.CHROME_HEADLESS; private DriverFactory() { } public static WebDriver getDriver() { return getDriver(DEFAULT_BROWSER_TYPE); } public static WebDriver getDriver(BrowserType browserType) { String driverPath; switch (browserType) { case CHROME: driverPath = BaseTest.class.getResource("/drivers/chromedriver.exe").getPath(); System.setProperty(CHROME_DRIVER_LOCATION_PROPERTY, driverPath); return new ChromeDriver(); case FIREFOX: driverPath = BaseTest.class.getResource("/drivers/geckodriver.exe").getPath(); System.setProperty(FIREFOX_DRIVER_LOCATION_PROPERTY, driverPath); return new FirefoxDriver(); case CHROME_HEADLESS: driverPath = BaseTest.class.getResource("/drivers/chromedriver.exe").getPath(); System.setProperty(CHROME_DRIVER_LOCATION_PROPERTY, driverPath); ChromeOptions options = new ChromeOptions(); options.setHeadless(true); return new ChromeDriver(options); default: throw new IllegalArgumentException("Configuration for browser " + browserType + " has not been created"); } } }
The last thing we need is adding setUpBrowser method to BaseTest class. The method has annotation @BeforeClass because WebDriver instance has to be created before first test is run. This method uses browser parameter from testNg xml configuration file and based on the value assign desired WebDriver to the driver variable. If you don't pass any value to browser variable (e.g. run selected test directly from your IDE) then default WebDriver is assigned.
package com.testcraftsmanship.model.base; import com.testcraftsmanship.model.config.BrowserType; import com.testcraftsmanship.model.config.DriverFactory; import com.testcraftsmanship.model.pages.GooglePage; import org.openqa.selenium.WebDriver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.annotations.BeforeClass; import org.testng.annotations.Optional; import org.testng.annotations.Parameters; public abstract class BaseTest implements PageInitializer { private static final Logger LOGGER = LoggerFactory.getLogger(BaseTest.class); private WebDriver driver; public BaseTest() { } @BeforeClass @Parameters("browser") public void setUpBrowser(@Optional("use default browser settings") String browser) { switch (browser) { case "firefox": driver = DriverFactory.getDriver(BrowserType.FIREFOX); break; case "chrome": driver = DriverFactory.getDriver(BrowserType.CHROME); break; default: driver = DriverFactory.getDriver(); LOGGER.info("Do not use parametrized run. Used default browser settings."); } } public WebDriver getDriver() { return driver; } protected GooglePage openApplication() { driver.get("http://google.com"); return newInstance(GooglePage.class); } protected void closeApplication() { driver.quit(); } }