The efficiency of our testing process at optimal costs with Headless Testing

Lakmali Bandara
Javarevisited
Published in
7 min readMay 23, 2022

The software testing industry has come up with new techniques (like agile methodology) to decrease time-to-delivery while ensuring quality product deliverables at reduced cost and efforts.

When compared to various application testing procedures, testing web apps is the trickiest one. The testers need to test applications on different browsers (which is difficult because there are many browsers in the market, and none can be sure of which browser users might use) by considering various parameters like integration, usability, UI, interoperability, and security. To increase efficiency and ease of testing web apps, Headless Browser Testing was developed.

Headless Browser & Headless Testing

Selenium Web driver is a web automation tool that enables you to run tests against different browsers. These browsers can be Internet Explorer, Firefox, or Chrome. To use a particular browser with Selenium you need a corresponding driver.

At test run, Selenium launches the corresponding browser called in the script and executes the test steps. You can see the browser and the test execution in action.

But, A headless browser is a web browser without a graphical user interface. This program will behave just like a browser but will not show any GUI to us, Selenium executes its tests in the background

There are several headless browsers available in the market, the following are the most popular ones:

  • Chrome
  • Firefox
  • HTMLUnit driver
  • PhoantomJS

What is Headless Browser Testing and What Does it Do?

Headless Browser Testing is a process of running the browser tests without the type of browser UI or GUI. In headless browser testing, to conduct cross-browser testing the tester can run test cases accurately and successfully without requiring the browser on which application needs to be tested.

In a Continuous Integration environment, this testing methodology is beneficial to run tests because the scaling of continuous testing is done efficiently, as there is no one to observe the visuals.

This type of browser has access to all webpages and without displaying them to the user this browser can move the webpage content to another program. As the headless browser programs run in the backend, like usual browsers, users get nothing to see on the screen starting the headless browser.

Even though no two browser’s implementations are the same, the headless browser can analyze and interpret webpages. This allows a headless browser to deliver the real browser perspective without demanding memory or cost incurred in test cases with actual browser GUI.

The reason behind using a headless browser or carrying out headless testing is that they are faster than normal browsers. Since you are not opening the browser GUI, you can ignore the time taken by a normal browser to load CSS, JavaScript, and render HTML.

With headless testing, you can observe 2x to 15x faster performance scaling. If performance is the critical aspect the testing process is aimed toward, then the headless browser may be a way to go.

Limitations of headless browser testing

·Headless browser testing is useful when we integrate our tests with the CI/CD pipelines where the test scripts run automatically without any human intervention.

In this scenario, the web browser doesn’t need to be launched because the CI/CD pipelines are run automatically at the night or in early the morning when no one is there to see the execution.

· Even if we are running a single test on a single browser it requires a substantial amount of resources. And if we run our tests in parallel then it may result in slower execution of tests.

· To overcome this issue we can execute our tests in a headless browser where the execution takes place without actually opening the browser. Which is much less hungry for system resources.

· The results are almost the same but without utilizing the GPU of the system.

So now you can understand the Advantages of Headless browser testing

· The execution time is much less as compared to normal test execution. This saves a lot of time when the number of tests is more.

· Headless mode is also useful when integrating our tests with the CI/CD pipelines, for automated execution of the tests. As it does not require the GUI for the execution of the tests.

· The overall performance of the tests is also better, as the overhead of opening the web browser is removed.

While observing the Advantage of headless testing, there are a few limitations we can observe from headless testing

Disadvantages Headless browser testing

· We cannot always use headless mode for execution. As to check the overall user experience from the end-users point of view we need to execute the tests the normal way.

· If the tests are failing because of some issues, it is difficult to debug the issues in headless mode. Normal execution is required in these scenarios.

· In some cases, we might encounter a bug that is only reproducible in headless mode. These types of bugs will not have much impact on the product.

Headless automation in selenium

As mentioned above, the Selenium web driver provides various drivers and configurations which help in running the selenium TC in headless mode.

  • Running Selenium test cases using a headless Chrome browser.
  • Running Selenium test cases using the headless Firefox browser.
  • Running Selenium test cases using HTMLUnitDriver
  • And Running Selenium test cases using PhantomJs

Headless Chrome Browser

Headless Chrome is a way to run the Chrome browser in a headless environment without the full browser user interface. Headless Chrome offers you a real browser context without the memory overhead of running a full version of Chrome. Google Chrome is available with headless execution since version 59. Selenium WebDriverprovides a class called “ChromeOptions”, which can specify certain configurations to change the default behavior of Chrome. One of those configurations is the “headless” mode, which launches the Chrome in headless mode while running the test cases

if (browserName != null && browserName.equals("chrome"))
{
Class<? extends WebDriver> driverClass = ChromeDriver.class;
ChromeDriverManager.getInstance(driverClass).setup();
driver = new ChromeDriver();
}
else if (browserName != null && browserName.equals("chromeHeadless"))
{
Class<? extends WebDriver> driverClass = ChromeDriver.class;
ChromeDriverManager.getInstance(driverClass).setup();
ChromeOptions options = new ChromeOptions();
options.setHeadless(true);
//options.addArguments("--headless");
driver = new ChromeDriver(options);
}

Headless Firefox Browser

For Headless Firefox, we have to work in the same way as we did in headless Chrome. First, we will set the path for the Gecko Driver (used for Firefox browser) and then set the options as headless. Here, we use the methods setHeadless (true) of the FirfoxOptions class provided by Selenium WebDriver.

else if (browserName != null && browserName.equals("firefox"))
{
Class<? extends WebDriver> driverClass = FirefoxDriver.class;
FirefoxDriverManager.getInstance(driverClass).setup();
FirefoxOptions options = new FirefoxOptions();
options.setHeadless(true);
driver = new FirefoxDriver(options);
}

HtmlUnitDriver

To implement headless testing, Selenium makes use of HtmlUnitDriver, which is another implementation of WebDriver, similar to FirefoxDriver, ChromeDriver, etc. HTMLUnitDriver is available as an external dependency and requires you to add the library explicitly.

Note: In the earlier versions of Selenium (before version 2.53), HtmlUnitDriver was available within the selenium library, and there was no need to download the jar externally. While this driver is still supported, it is now a separate dependency and uses the Html Unit framework. These dependencies need to add to the project in the same way as other jars add and or you can add the maven dependency

To download the HtmlUnitDriver dependencies

1. Navigate to https://github.com/SeleniumHQ/htmlunit-driver/releases.

2. Click on the latest version of the HTML unit driver

3. Add to the java Build path or you can add maven dependency

<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>htmlunit-driver</artifactId>
<version>3.61.0</version>
</dependency>

NOTE 01—

This syntax will construct a new instance with JavaScript disabled, and the default browser version. If your application needs some of the JavaScript functionalities, you can enable the same, with the configurations as mentioned in the following article:

For Enabling JavaScript support in HtmlUnitWebDriver

HtmlUnitWebDriver, by default, doesn’t enable JavaScript. It means in the above code, if you try to execute JavaScript, an error will be thrown, stating that JavaScript is not enabled. To create a driver instance with JavaScript enabled, you can use the constructor HtmlUnitDriver (boolean enable javascript) and set the value as true as shown below

else if (browserName != null && browserName.equals("HtmlUnitDriver"))
{
driver = new HtmlUnitDriver(true);

}

So, this will create an instance of the HtmlUnitDriver, with JavaScript enabled.

NOTE 02 —

Now, when we ran the test cases with Default options of HTMLUnitDriver, it picked the browser. This browser was by default on your machine. If you want to execute the test cases in a specific browser version also, you can also do the same with the help of HTMLUnitDriver. Let’s understand how we can achieve the same:

HtmlUnitDriver allows you to select the version of the browser that you would like to run your tests. The main supported browsers are Chrome, Firefox, and Internet Explorer. We can use the different versions of the browser bypassing the values in the constructor that will create a new instance with the specified version

else if (browserName != null && browserName.equals("HtmlUnitDriver"))
{
driver = new HtmlUnitDriver(BrowserVersion.EDGE);

}

PhantomJS

PhantomJS is a headless browser with JavaScript API. It is an optimal solution for Headless Website Testing, access, and manipulating webpages & comes with the standard DOM API.

In order to use PhantomJS with Selenium, one has to use GhostDriver. GhostDriver is an implementation of Webdriver Wire protocol is simple JS for PhantomJS.

The latest release of PhatomJS has integrated GhostDriver and there is no need to separately install it.

else if (browserName != null && browserName.equals("phantomjs"))
{
System.setProperty("phantomjs.binary.path","/Users/preethi/Documents/Presonal/Own Project/phantomjs-2.1.1-macosx/bin/phantomjs");
driver= new PhantomJSDriver();
}

Here is the full implementation of the code

class BrowserFactory {
static WebDriver getBrowser(String browserName) {

WebDriver driver;

if (browserName != null && browserName.equals("chrome"))
{
Class<? extends WebDriver> driverClass = ChromeDriver.class;
ChromeDriverManager.getInstance(driverClass).setup();
driver = new ChromeDriver();
}
else if (browserName != null && browserName.equals("chromeHeadless"))
{
Class<? extends WebDriver> driverClass = ChromeDriver.class;
ChromeDriverManager.getInstance(driverClass).setup();
ChromeOptions options = new ChromeOptions();
options.setHeadless(true);
//options.addArguments("--headless");
driver = new ChromeDriver(options);
}
else if (browserName != null && browserName.equals("firefox"))
{
Class<? extends WebDriver> driverClass = FirefoxDriver.class;
FirefoxDriverManager.getInstance(driverClass).setup();
FirefoxOptions options = new FirefoxOptions();
options.setHeadless(true);
driver = new FirefoxDriver(options);
}
else if (browserName != null && browserName.equals("HtmlUnitDriver"))
{
driver = new HtmlUnitDriver(BrowserVersion.EDGE);

}
else if (browserName != null && browserName.equals("phantomjs"))
{
System.setProperty("phantomjs.binary.path","/Users/preethi/Documents/Presonal/Own Project/phantomjs-2.1.1-macosx/bin/phantomjs");
driver= new PhantomJSDriver();
}
else {
Class<? extends WebDriver> driverClass = ChromeDriver.class;
ChromeDriverManager.getInstance(driverClass).setup();
driver = new ChromeDriver();
}

driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(Wait.EXPLICIT_WAIT, TimeUnit.SECONDS);
return driver;
}
}

Thank you for reading …

--

--

Lakmali Bandara
Javarevisited

Technical Lead Quality Engineering | Framework Developer | API Tester | Blogger