Going headless seems to be all the rage these days, so let's have a look at how we can add support a headless browser to our burgeoning framework.
It's actually a relatively simple change; first, we are going to use this code to modify our POM to add a <headless> property (we are going to set it to true because you are always going to want to start of running things in headless mode, right?):
<properties>
<project.build.sourceEncoding>UTF-
8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-
8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<!-- Dependency versions -->
<selenium.version>3.12.0</selenium.version>
<testng.version>6.14.3</testng.version>
<!-- Plugin versions -->
<driver-binary-downloader-maven-plugin.version>1.0.17
</driver-binary-downloader-maven-plugin.version>
<maven-compiler-plugin.version>3.7.0
</maven-compiler-plugin.version>
<maven-failsafe-plugin.version>2.21.0
</maven-failsafe-plugin.version>
<!-- Configurable variables -->
<threads>1</threads>
<browser>firefox</browser>
<overwrite.binaries>false</overwrite.binaries>
<headless>true</headless>
</properties>
Then, we need to pass that in through maven-failsafe-plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven-failsafe-plugin.version}</version>
<configuration>
<parallel>methods</parallel>
<threadCount>${threads}</threadCount>
<systemPropertyVariables>
<browser>${browser}</browser>
<headless>${headless}</headless>
<!--Set properties passed in by the driver binary
downloader-->
<webdriver.chrome.driver>${webdriver.chrome.driver}
</webdriver.chrome.driver>
<webdriver.ie.driver>${webdriver.ie.driver}
</webdriver.ie.driver>
<webdriver.opera.driver>${webdriver.opera.driver}
</webdriver.opera.driver>
<webdriver.gecko.driver>${webdriver.gecko.driver}
</webdriver.gecko.driver>
<webdriver.edge.driver>${webdriver.edge.driver}
</webdriver.edge.driver>
</systemPropertyVariables>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
Finally, we will use this code to update our DriverType enum to read in the new headless system property and apply it to the CHROME and FIREFOX entries:
package com.masteringselenium.config;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.edge.EdgeOptions;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.ie.InternetExplorerOptions;
import org.openqa.selenium.opera.OperaDriver;
import org.openqa.selenium.opera.OperaOptions;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.safari.SafariDriver;
import org.openqa.selenium.safari.SafariOptions;
import java.util.HashMap;
public enum DriverType implements DriverSetup {
FIREFOX {
public RemoteWebDriver getWebDriverObject
(DesiredCapabilities capabilities) {
FirefoxOptions options = new FirefoxOptions();
options.merge(capabilities);
options.setHeadless(HEADLESS);
return new FirefoxDriver(options);
}
},
CHROME {
public RemoteWebDriver getWebDriverObject
(DesiredCapabilities capabilities) {
HashMap<String, Object> chromePreferences =
new HashMap<>();
chromePreferences.put("profile.password_manager_enabled"
, false);
ChromeOptions options = new ChromeOptions();
options.merge(capabilities);
options.setHeadless(HEADLESS);
options.addArguments("--no-default-browser-check");
options.setExperimentalOption("prefs",
chromePreferences);
return new ChromeDriver(options);
}
},
IE {
public RemoteWebDriver getWebDriverObject
(DesiredCapabilities capabilities) {
InternetExplorerOptions options = new
InternetExplorerOptions();
options.merge(capabilities);
options.setCapability(CapabilityType.ForSeleniumServer.
ENSURING_CLEAN_SESSION, true);
options.setCapability(InternetExplorerDriver.
ENABLE_PERSISTENT_HOVERING, true);
options.setCapability(InternetExplorerDriver.
REQUIRE_WINDOW_FOCUS, true);
return new InternetExplorerDriver(options);
}
},
EDGE {
public RemoteWebDriver
getWebDriverObject(DesiredCapabilities
capabilities) {
EdgeOptions options = new EdgeOptions();
options.merge(capabilities);
return new EdgeDriver(options);
}
},
SAFARI {
public RemoteWebDriver getWebDriverObject
(DesiredCapabilities capabilities) {
SafariOptions options = new SafariOptions();
options.merge(capabilities);
return new SafariDriver(options);
}
},
OPERA {
public RemoteWebDriver getWebDriverObject
(DesiredCapabilities capabilities) {
OperaOptions options = new OperaOptions();
options.merge(capabilities);
return new OperaDriver(options);
}
};
public final static boolean HEADLESS =
Boolean.getBoolean("headless");
}
We can now run our project again exactly the same way as before:
mvn clean verify -Dthreads=2
You will see the test start up again, but this time you won't see a browser window pop up. Everything should work exactly as before and the tests should pass as expected. If you want to see the browser window pop up again, you can just set headless to false:
mvn clean verify -Dthreads=2 -Dheadless=false