ChromeDriver Performance C#

· 2 min

Scenario

You have a good suite of automated browser tests. But the web app has different user roles and scenarios, and the one-minute suite has grown to five minutes. Now it's a bottleneck in the development lifecycle. I ran into exactly this.

This post looks at cutting the time between operations, and with it the total run time of the suite.

The setup

Web page

Every test loads the same page. It has multiple round trips, images, videos and several megabytes of content, to simulate a sizeable, real-world web app. On static HTML, your tests will probably be fast however they're written. Here are the Google PageSpeed Insights results for the page:

Software

Performance tests

Requests to a remote server bring in plenty of variables outside our control. Explicit and implicit waits don't help, because they poll the DOM until a specific element appears. To separate out server variance, there are two test sets, one against a local server and one remote.

Finding UI elements

The most common operation is finding elements on a page and checking their values match expectations. ChromeDriver exposes FindElement and FindElements for this. There are several ways to find elements, and these tests cover the three most popular:

Setup

A blank C# console application with the minimum code needed, timing each operation with the Stopwatch class. Each result is an average over an arbitrary 1,500 iterations, 500 per lookup method.

Test results

Finding an element by ID is the fastest, which is in line with the documentation.

Optimisations

With a baseline, the same two tests can measure each optimisation.

Browser extensions

Pages make more and more HTTP requests, especially to third parties. A faster page should mean faster tests, so filtering out some of those requests may help. This test uses uBlock Origin, available as a Chrome extension. I chose uBlock because it has a light footprint and generally makes Chrome leaner, using less CPU and RAM.

Setup

Get the extension's .crx file, using a third-party tool such as CRX Extractor, and load it into the ChromeDriver instance:

var cdOptions = new ChromeOptions();
cdOptions.AddExtension(@"C:\temp\uBlock-Origin_v1.14.20.crx");

// Directory containing the ChromeDriver executable
var cdFilePath = @"C:\tempMonitor";

var cd = new ChromeDriver(cdFilePath, cdOptions, TimeSpan.FromSeconds(30));

Results

Compared with the remote test:

With uBlock, loading the remote page and finding elements is 200-300ms faster. It also makes it less likely that a hanging third-party request stops the page from ever finishing loading, which would eventually throw a TimeOutException.

Headless Chrome

Chrome can now run headless: no GUI, though you can still see the process in Process Explorer. Headless is faster because nothing is drawn to the screen, but there are drawbacks, such as simulating user input and not being able to see a problem on the page. Leaving those aside, here's the performance impact.

Setup

Pass the --headless argument. Headless mode logs a lot of warnings to the console, so this hides them too:

var cdOptions = new ChromeOptions();

cdOptions.AddArgument(@"--headless");
cdOptions.AddArguments(@"--log-level=3");

// Directory containing the ChromeDriver executable
var cdFilePath = @"C:\tempMonitor";

var cd = new ChromeDriver(cdFilePath, cdOptions, TimeSpan.FromSeconds(30));

Results

Headless mode takes 300-400ms off the tests without extensions. Across a large suite, that adds up to a big saving, and headless also makes it easier to run tests in parallel.