The Battle of the Browser Window

Standard

Automating tests for a user interface (UI) is certainly not the easiest way of implementing test automation. When deciding to automate against a UI one needs to overcome a number of obstacles. For example, the type of platform on which the UI runs can have effects on the performance of the test execution. And various aspects of size—such as the desktop resolution or the size of an application window—can seriously affect automated test execution. In this article I would like to discuss the size of an application window of a UI that runs through a browser.

The browser that is used for UI test automation is Google Chrome and the creation of automated tests is done using Java 8 and Selenium WebDriver. The environment in which the tests are developed is a Windows 7 environment. Chrome is the only browser that is used for test automation. Firefox was tried but not considered as an alternative because Chrome worked sufficiently. Two headless browsers were tried: Headless Chrome and PhantomJS. Both browsers failed to handle overlays in the application correctly and were therefore abandoned.

In the project that I am working on, every developer has his own virtual development environment. For the development of the page objects that interact with the pages of the application, the developer will use the Chrome browser on a desktop. This desktop has a resolution of 1920 x 1080 pixels. The Chrome browser is always started maximized and therefore we can assume that the browser window size in which the tests are developed is roughly 1900 x 980 pixels. Browser toolbars and scrollbars will consume some of the desktop size. It is not within the scope of the project to develop tests against a smaller browser window. The fact that every developer is running tests against a window size of roughly 1900 x 980 pixels means that the code in the page objects is optimized for this size. In the code of the testing framework it is expected that the HTML elements that we want to access are inside browser window. Once an element is outside the window, one needs an extra line of code to scroll to that element. There are several ways to do this. If the automation code is run in a smaller window an element that was inside the larger window might suddenly cause the code the automation code to fail, throwing an ‘element is not clickable’ WebDriver exception. So running the automated UI tests on window size that is smaller than the size in which the tests are developed may require code changes.

Questions about resolution and size

As long as tests are only run on the developer’s personal development environment, there are no problems with resolution and size. The developer has full control over both. But as soon as tests are run on a different environment then we need to pay special attention to the resolution and the size of the browser window This is the case when UI tests are, for example, run automatically on a daily basis on a Windows server. The tests are scheduled in a Jenkins job and are executed using Maven. But do we know the resolution and size when we run UI tests on the server?

There is no easy answer to this question. In order to have a resolution, one needs a desktop. On Windows, a desktop is tied to a user account. So we need to establish which user account is used to run the tests. On Windows Jenkins runs as a Windows service. The Windows service runs by default under the LocalSystem account, which is a very specific account. It has extensive privileges and there are opinions that Jenkins should not be running under this account because of security considerations. It also appears that there is no Windows desktop associated with the LocalSystem account. I was unable to find conclusive evidence for whether or not the LocalSystem account has a desktop. It is observed that the UI tests that run on the server are capable of starting a browser so there must be a desktop but it is unclear where that desktop comes from and how it can be controlled. What is clear is that the resolution of the desktop and the size of the browser are considerably smaller than on the development environment. It causes tests to fail with the exception I mentioned before. To make sure that the window size is the root cause of failure, we want to determine the exact sizes of the desktop and the browser.

Determining desktop resolution and window size

Once UI tests are run through Jenkins it is not possible to observe the browser while the tests are running. But there are at least two ways to verify the size of the browser window. One is to take a screenshot using WebDriver. The other one is to gather the information programmatically and write it to the application log.

Using the Java Abstract Window Toolkit (AWT) it is possible to get the screen resolution. In the code example below the width and height are logged in the application log using the method logScreenResolution. The browser window size can easily be established using Selenium WebDriver. In the example below the size is logged in the method logWindowSize.

import java.awt.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class Driver {
    private static final Logger LOG = LoggerFactory.getLogger(Driver.class);
    private WebDriver driver;

    public Driver() {
        WebDriver driver = new ChromeDriver();
    }

    private static void logScreenResolution() {
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        double width = screenSize.getWidth();
        double height = screenSize.getHeight();
        LOG.info("Desktop resolution: {} x {}", width, height);
    }

    private void logWindowSize() {
        LOG.info("Browser screen size {}", driver.manage().window().getSize());
    }

Using these methods I consistently encounter a desktop resolution far less than the desired 1920 x 1080. So it appears that whatever desktop is conjured up on the server is too small for running the UI tests. Furthermore I observe that the browser window size is consistently slightly larger than the desktop resolution. It seems odd that a browser window can be larger than the desktop but I ascribe the difference to the non-identical ways of measuring.

I spend some time digging through Google search results in order to find some fix for the desktop resolution problem on Windows—some way to control the desktop—but no solution comes up. It should be an option to create a new Windows user on the server, configure this user (give it the proper desktop) and have the Jenkins Windows service run under this account. However, I decide not to explore this option.

Setting the browser window size

There are ways to control the window size of the browser. But it appears that there are no ways to create a browser window that is larger than the desktop resolution. In other words, a browser window will always be confined within the dimensions of the desktop. Given that precondition, it is not very relevant to look at setting the browser size unless you specifically want a smaller window. But since it is a possibility I am including these options. For Chrome there are two ways to set the window size, one using the ChromeOptions, the other one using the setSize method of Selenium WebDriver. I think both ways can be used interchangeably. Note that there are also two ways to maximize the browser window. In the example below the window is maximized after the size is set. This is not very relevant since maximizing will create a browser window that fills the entire space of the desktop. It will override the set window size. But for the sake of showing both ways to manipulate the window size, they are done within the same method.

import org.openqa.selenium.Dimension;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class Driver {
    private WebDriver driver;

    public static WebDriver getChromeDriverUsingOptions() {
        ChromeOptions options = new ChromeOptions();
        options.addArguments("window-size=1400,1000");
        options.addArguments("--start-maximized");
        return new ChromeDriver(options);
    }

    public static WebDriver getChromeDriver() {
        WebDriver driver = new ChromeDriver();
        driver.manage().window().setSize(new Dimension(1400, 1000));
        driver.manage().window().maximize();
        return driver;
    }
}

 

The reliable desktop

Since the desktop resolution seems to be the variable that needs to be controlled in order to get to a proper window size, the quest is on for a reliable desktop. One of the ways to get a reliable and controllable desktop on the Jenkins Windows server is to create a virtual machine on that server that has such a desktop. And this can be done using Docker. Docker is a virtualization platform that allows for the easy creation and running of (Linux) machines on a server. I will not go into the intricacies of installing Docker on Windows; it is beside the point of this article. In order to run a Docker machine you need an image, a package that contains everything one needs to run an application. Selenium has developed several Docker images that can be downloaded and run instantly. The project is called Docker Selenium. The project sports an image in which a Chrome browser can be run. This image is called Standalone Chrome. Actually the image runs Chromium—the open source variety of the Chrome browser—but for the project that I work on this is sufficient. The question is whether the desktop of this image can be controlled. When we look at the base image of Standalone Chrome, we see that it is based on Ubuntu 16.04. Ubuntu 16.04 has a desktop, but the desktop is not used by Chromium. Instead, the X Virtual Framebuffer (Xvfb) is used to run Chromium. Xvfb is a virtual framebuffer, which means that it acts as a graphical interface on systems on which there is no display hardware and no graphical interface. Within Xvfb there is no actual desktop so there is no desktop resolution. Therefore it is possible to define a browser window of any size. This definitely solves the problem and brings an end to the battle of the browser window.

Conclusion

Having to use a browser for the testing of an application can be a nuisance in many ways. One of the problems is that a browser requires a graphical user interface. When tests are run on a Windows server it can be difficult to control the properties of the graphical user interface such as the resolution of desktop and the size of the browser window. Running a browser on a headless interface takes away the need to control a desktop. There is a variety of headless browsers, such as Headless Chrome or PhantomJS. But difficulties may be encountered when interacting with the application through a headless browser. The ultimate solution is to run a regular browser on a headless desktop. This way, the graphical user interface is provided by a virtual framebuffer. There are limitations with regards to the operating system (Linux) and the type of browser that can be used. But the combination of Chromium, Linux, Xvfb and—if desired—Docker can create a reliable and controllable environment for UI testing. Ironically, the struggle with the desktop resolution ends by eliminating the desktop.

By desktop resolution I indicate the dimensions of the desktop, not the pixel density. So ‘desktop resolution’ is a misnomer but it is used to make a clear distinction between the size of the desktop and the size of the browser window.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s