Topics

Featured in Development

Peter Alvaro talks about the reasons one should engage in language design and why many of us would (or should) do something so perverse as to design a language that no one will ever use. He shares some of the extreme and sometimes obnoxious opinions that guided his design process.

Featured in AI, ML & Data Engineering

Today on The InfoQ Podcast, Wes talks with Katharine Jarmul about privacy and fairness in machine learning algorithms. Jarul discusses what’s meant by Ethical Machine Learning and some things to consider when working towards achieving fairness. Jarmul is the co-founder at KIProtect a machine learning security and privacy firm based in Germany and is one of the three keynote speakers at QCon.ai.

Featured in Culture & Methods

Organizations struggle to scale their agility. While every organization is different, common patterns explain the major challenges that most organizations face: organizational design, trying to copy others, “one-size-fits-all” scaling, scaling in siloes, and neglecting engineering practices. This article explains why, what to do about it, and how the three leading scaling frameworks compare.

Selenium is a well-known, powerful tool for automated testing in web browsers. While Selenium Web driver supports all the major browsers, you don’t always want the costs of testing in a real browser. Headless browsers to the rescue! The examples in this article are in a GitHub repo. All run with JUnit 5 and Maven. Java 11 vs Java 8 support is noted for each example.

What are the benefits of a headless browser?

Headless browsers run without a user interface (UI.) A big benefit of using one for testing is performance - since headless browsers don’t have a UI, they are faster than real browsers.

There’s another advantage of some headless browsers – dependencies. When testing on a continuous integration server like Jenkins, the machine might not have a real browser installed. And depending on your environment, you might not have permissions to install one.

Related Vendor Content

One the other hand headless browsers that require a “real” browser to be installed are great for development. For example, both Chrome and Firefox have the option to run in headless mode. It is really helpful when debugging a Selenium script to temporarily turn off headless mode and watch the program run. That way you can visually see where things go haywire.

HtmlUnitDriver – the initial headless driver

In the past, Selenium came with a built in headless driver called HtmlUnitDriver. While this driver is still supported, it is now a separate dependency and, unsurprisingly, uses the Html Unit framework. Prior to Single Page Applications and largely AJAX based pages, this driver was an excellent choice. You have the ability to choose whether to run the page JavaScript, it runs in memory and is very fast. It’s still a good choice for web pages with a good amount of HTML data on them.

The following code shows how to run a basic test that uses Selenium with HtmlUnitDriver. It works because InfoQ’s home page is designed to be functional without JavaScript. This example is available in both Java 8 and Java 11 versions in the GitHub repo.

However, uncommenting the line that enables JavaScript is a different story. After spitting out a whole pile of JavaScript warnings, it fails with EcmaError: TypeError: Cannot call method "then" of undefined.

Since many pages won’t load at all without JavaScript, this shows the need for a headless driver with better JavaScript support.

Reading the announcement and comments, the intent was clearly to move to Chrome Driver. I don’t recommend using PhantomJS for anything new. Aside from not being supported, I switched two of my projects over to Chrome Driver because PhantomJS doesn’t handle JavaScript well enough for the most current JavaScript libraries. Since Chrome Driver uses a real browser, that’s not a problem for it.

Chrome Driver

Chrome provides a headless mode, which works well overall. The biggest downside is that you need to be able to install Chrome. You don’t need a UI, but installing software is not always possible.

Chrome Driver also requires an executable to be downloaded. I cheated a bit here. I keep the executable in the same directory as the project (or in a binary repository and copy it to the workspace.) I then have the Java test itself set the permissions. Similarly, I have the Java test set the system property within the Java process to that location. A bit of a cheat, I know, but it does keep almost everything self contained. “Almost” because it still requires Chrome itself to be installed. This works great on my personal projects. When sharing code with others though it falls apart because they also need to download the executable.

There are both Java 8 and Java 11 versions in the repo. Both require you to download the executable and replace it in the chrome-driver directory.

The two execute script lines are to work around a problem with prompts in another application I am testing. I’ve instructed the driver to ignore them. (Although it’s not needed here, it was enough of a pain to figure out that I use it everywhere I use Chrome Driver so I never have to solve that problem!)

Another disadvantage of using Chrome Driver is that it needs to be updated periodically to support later versions of Chrome.

Gecko Driver

Chrome was first to the party of headless browser testing, and so that is the one I have the most experience with. However Firefox also has a headless mode. which works just like the Chrome one. You download the Gecko Driver and use selenium-firefox-driver in your pom.xml

JBrowser Driver

While I like Chrome Driver, it does require Chrome to be installed. I have a project where I run a daily check to tell me when Oracle changes the certification objectives. The server I run it on does not have Chrome installed. Recently, Oracle updated their website to be more AJAX heavy. PhantomJS no longer met my needs so I started looking for a more modern driver.

I found JBrowser Driver. There have been regular commits in the last year including updates to Selenium versions. It has a good license (Apache 2.) Version 1.0.0 just came out over the summer. However there have been pre-1.0 releases for almost three years.

The biggest downside to JBrowser Driver is that they only support Oracle JDK Java 8 at present. This is the version of Java that will no longer have patches for business users in January 2019 and for individual users in December 2020.

Note on Java FX:

In Java 7, Java FX was a separate download

In Java 8, Java FX was part of Oracle JDK but not Open JDK

In Java 11, Java FX is available for free via a Maven dependency using OpenJFX

Also, in Java 11, the Robot.java class changed packages from com.sun.glass.ui to javafx.scene.robot. This means that you can’t just use OpenJFX’s version of JavaFX with your Open JDK 11 and expect JBrowser Driver to work.

The code is straightforward and the Java 8 version is in the GitHub repo.

Conclusion – comparing the options

There’s lots of choice for headless browser testing with Java and Selenium. And like any good engineering problem, there are tradeoffs to choose between. This table lists your main choices. The lesson is that if you need to be able to run a headless Selenium driver without a real browser installed, you need to stay on Java 8 for the time being.

Library

JavaScript power

Supports Java 8

Supports Java 11

Requires browser installation

Html Unit Driver

Low

Yes

Yes

No

Phantom JS (no longer supported)

Medium

Yes

No

No

Chrome Driver

High

Yes

Yes

Yes – Chrome

Gecko Driver

High

Yes

Yes

Yes – Firefox

JBrowser Driver

High

Yes

No

No

About the Author

Jeanne Boyarsky is a Java developer and part time ScrumMaster. She co-authored Wiley’s OCA/OCP 8 certification books and will be updating them for the next version of the certification. In addition to volunteering at CodeRanch, she mentors the programmers on a high school robotics team and won a mentorship award. Jeanne has spoken at conferences including JavaOne, QCon, DevNexus and SpringOne.

Community comments

Selenium Docker Containers

Your message is awaiting moderation. Thank you for participating in the discussion.

Something I think worth mentioning are the Selenium headless docker containers. This solves the install problem (for the most part). You can even run them in debug mode and connect to them using VNC when you need to figure out what the heck it looks like on the screen when selenium says it can't find an element.