Upgrading to Selenium 4 for Sauce Labs Testing
This doc will guide you through how to upgrade to Selenium 4, which was released in late 2021.
Selenium 4 is designed to be a straightforward drop-in replacement for previous versions, however, you'll need to be aware of the new and deprecated features that may impact your Sauce Labs automated tests. This is especially important if you've built custom functionalities in your testing framework.
What You'll Learn
- How to adjust your tests and dependencies to work with Selenium 4
- How to prevent and resolve potential issues that could arise during your upgrade to Selenium 4
What You’ll Need
- A Sauce Labs account (Log in or sign up for a free trial license)
- A working development environment for one of the supported Selenium 4 programming languages: JavaScript, Java, Python, Ruby, or C#.
Although Selenium 4 has JavaScript bindings, we recommend using WebdriverIO instead when running tests on Sauce Labs.
W3C WebDriver-Compliant Sessions
Selenium 4 deprecates support for legacy JSON Wire Protocol (JWP). As part of this change, Selenium is moving away from the less-structured Desired Capabilities classes to Browser Options classes. Here are some of the benefits:
- Facilitates creation of W3C WebDriver-compliant capabilities.
- Simplifies the configuration needed to start a new session.
- Allows you to set both defined W3C Capabilities and browser-specific settings.
- Reduces the chances of browser misconfiguration.
Capabilities
You can use the following defined W3C WebDriver-compliant capabilities in your Sauce Labs tests:
browserName
browserVersion
platformName
acceptInsecureCerts
pageLoadStrategy
proxy
timeouts
unhandledPromptBehavior
Any capability not listed above must include a vendor prefix (i.e., moz:firefoxOptions
, goog:chromeOptions
, ms:edgeOptions
). This rule applies to both browser-specific capabilities and Sauce Labs-specific capabilities.
As an example, Firefox-specific capabilities need to be nested inside of moz:firefoxOptions
or other moz:<xyz>
keys. If you use a Browser Options class, no additional action is required. For Sauce Labs testing, however, you'll need to create a Hash or Dictionary of Sauce Labs-specific settings and place it inside of a sauce:options
object. See the examples in the next section.
Converting Capabilities to Options
In the snippets below, Recommended Code contains our recommendations for Selenium 4, while those marked Deprecated contain code commonly used in Selenium 3.x or below.
All valid sauce:options
parameters listed in the snippets are described in our Test Configuration Options documentation.
Use our Platform Configurator to auto-generate test configuration options in the language of your choice to copy and paste into your Selenium source code.
- Java
- Python
- Ruby
- C#
loading...
DesiredCapabilities caps = DesiredCapabilities.firefox();
caps.setCapability("platform", "Windows 10");
caps.setCapability("version", "92");
caps.setCapability("build", myTestBuild);
caps.setCapability("name", myTestName);
WebDriver driver = new RemoteWebDriver(new URL(sauceUrl), caps);
loading...
caps = {}
caps['browserName'] = 'firefox'
caps['platform'] = 'Windows 10'
caps['version'] = '92'
caps['build'] = my_test_build
caps['name'] = my_test_name
driver = webdriver.Remote(sauce_url, desired_capabilities=caps)
loading...
caps = Selenium::WebDriver::Remote::Capabilities.firefox
caps[:platform] = 'Windows 10'
caps[:version] = '92'
caps[:build] = my_test_build
caps[:name] = my_test_name
driver = Selenium::WebDriver.for :remote, url: sauce_url, desired_capabilities: caps
loading...
DesiredCapabilities caps = new DesiredCapabilities();
caps.SetCapability("browserName", "firefox");
caps.SetCapability("platform", "Windows 10");
caps.SetCapability("version", "92");
caps.SetCapability("build", myTestBuild);
caps.SetCapability("name", myTestName);
var driver = new RemoteWebDriver(new Uri(SauceURL), capabilities);
Remote WebDriverBuilder
Java only
An alternative way to start your session in Java is with the RemoteWebDriverBuilder
. This class has a few advantages for Sauce Labs users, including automatic driver augmentation (this is required for several of the new features below), and the ability to set HTTP Client settings like read timeouts.
loading...
New Features
Here are the new Selenium 4 features that you can use in your Sauce Labs tests, along with code snippet examples for each supported programming language.
Relative Locators
Relative locators allow you to identify elements in relationship to each other as they are displayed on the page, using natural, language-friendly terms, such as “above”, “below”, “left of”, “right of”, and “near”.
If you change the browser window size or add/remove anything on your webpage, this could change which element is located.
- Java
- Python
- Ruby
- C#
loading...
loading...
loading...
loading...
New Window
This feature allows you to create and switch to a new (blank) tab or window.
- Java
- Python
- Ruby
- C#
loading...
loading...
loading...
loading...
loading...
loading...
loading...
loading...
Print Page
This feature allows you to print a page as a PDF in Chrome, Firefox and Edge. You can apply customizations including (but not limited to) page size, range, margins, background, and shrink-to-fit. Here are code examples with the defaults:
For Chrome and Edge, this only works in Headless mode.
- Java
- Python
- Ruby
- C#
loading...
loading...
loading...
loading...
Element Attribute vs Property
The Selenium 3.x method for getting an element's attribute does not actually give you the element's attribute.
Selenium 4 better clarifies the difference between an element and an attribute, and provides you with the value you likely intended. Because this magic can not be precisely specified for W3C WebDriver capabilities, two new methods were created.
The original method hasn't changed, but using it will be slightly less performant on Sauce Labs, as well as less precise. The new methods are named slightly differently in each language.
Below are some examples showing the behavior of these attribute and property methods.
- Java
- Python
- Ruby
- C#
loading...
loading...
loading...
loading...
Chromium Edge Options
Selenium 4 allows you to apply custom Chromium Edge Options.
When the latest version of Selenium 3 was released, Microsoft Edge was still being implemented with the now-deprecated EdgeHTML browser engine. None of the custom options for working with the Chromium version of Edge were available in Selenium 3.
- Java
- Python
- Ruby
- C#
loading...
loading...
loading...
loading...
Timeout Getters
This is a long-requested feature. Selenium 3 allowed you to set timeouts whenever you liked, but did not provide a way to query the driver for the current timeout values. Selenium 4 provides that ability now.
Best practice is to set the timeout values in the Options class when starting the session and then ignore them during the test (i.e., do not use the setters or getters).
- Java
- Python
- Ruby
- C#
loading...
loading...
loading...
loading...
Network Conditions
Chrome and Edge only
Selenium 4 provides a set of parameters to modify network conditions, such as:
- Going offline
- Setting a latency for the connection
- Altering the upload or download throughput
This can be useful to test web apps under different network conditions.
Sauce Labs also provides the ability to throttle network settings through our Extended Debugging feature.
- Java
- Python
- Ruby
- C#
loading...
loading...
Click here to see the full C# example of setting Network Conditions. The C# implementation of this is a little more complex.
loading...
Full-Page Screenshots
Firefox only
Features like "infinite scroll" make it impossible to explicitly define what a "full page" entails for a W3C specification. As such, the default screenshot method in Selenium 3 only returns what is visible in the Viewport. For Selenium 4, Mozilla implemented a separate method to allow for a full-page screenshot in Firefox.
- Java
- Python
- Ruby
- C#
loading...
loading...
loading...
Install and Uninstall Add-ons
Firefox only
All other browser drivers except for Firefox allow you to install extensions with the Browser Options class. For Firefox, you'll need to install a separate method after the browser has been started.
- Java
- Python
- Ruby
- C#
loading...
loading...
Click here to see the full example of Installing and Uninstalling Add-ons. The C# implementation of this is a little more complex.
loading...
Change Preferences During Session
Firefox only
In Selenium 3, you can only set preferences in the Capabilities at the beginning of a test. Firefox has provided a way in Selenium 4 to update things whenever you want during a session. This is done by toggling the context between "chrome" and "content".
Here are some examples of using the "chrome" context to change the default accepted language of the browser:
Most Selenium commands are not valid in the "chrome" context. Be sure to switch back after using it.
- Java
- Python
- Ruby
- C#
loading...
loading...
Click here to see the full example of Changing Preferences During a Session. The C# implementation of this is a little more complex.
loading...
Bidirectional APIs
We support all new Selenium 4 features except for Bidirectional APIs. While we're working hard to add full support, we do provide similar functionality through our Extended Debugging feature, which allows you to:
- Intercept network requests to mock backends
- Throttling performance of both network and CPU
- Access console and network logs
Upgrading Your Dependencies
Check the sections below to install Selenium 4 and have your project dependencies upgraded.
The process of upgrading Selenium depends on which build tool is being used. We will cover the most common ones for JavaScript, Java (Maven and Gradle), Python, Ruby, and C#.
- JavaScript
- Java/Maven
- Java/Gradle
- Python
- Ruby
- C#
- Execute
npm install selenium-webdriver
- or update your package. json and run npm install:
{
"name": "selenium-tests",
"version": "1.0.0",
"dependencies": {
"selenium-webdriver": "^4.0.0"
}
}
loading...
loading...
mvn clean compile
on the same directory where the pom.xml
file is.plugins {
id 'java'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
implementation group: 'org.seleniumhq.selenium', name: 'selenium-java', version: '3.141.59'
}
test {
useJUnitPlatform()
}
plugins {
id 'java'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
implementation group: 'org.seleniumhq.selenium', name: 'selenium-java', version: '4.0.0'
}
test {
useJUnitPlatform()
}
./gradlew clean build
on the same directory where the build.gradle
file is. To view all Java releases, head to the MVNRepository.pip install selenium==4.0.0
gem install selenium-webdriver
gem 'selenium-webdriver', '~> 4.0'
PM> Install-Package Selenium.WebDriver -Version 4.0.0
Potential Errors and Deprecation Messages
Below are code examples that can help resolve deprecation messages you might encounter after upgrading to Selenium 4.
Find Element(s) Utility Methods
Java only
FindsBy
interfaces, utility methods to find elements in the Java bindings, have been removed, as they were meant for internal use only. In Example 2, you'll see that all the findElements*
have been removed as well.
Example 1
- Selenium 4
- Legacy
driver.findElement(By.className("className"));
driver.findElement(By.cssSelector(".className"));
driver.findElement(By.id("elementId"));
driver.findElement(By.linkText("linkText"));
driver.findElement(By.name("elementName"));
driver.findElement(By.partialLinkText("partialText"));
driver.findElement(By.tagName("elementTagName"));
driver.findElement(By.xpath("xPath"));
driver.findElementByClassName("className");
driver.findElementByCssSelector(".className");
driver.findElementById("elementId");
driver.findElementByLinkText("linkText");
driver.findElementByName("elementName");
driver.findElementByPartialLinkText("partialText");
driver.findElementByTagName("elementTagName");
driver.findElementByXPath("xPath");
Example 2
- Selenium 4
- Legacy
driver.findElements(By.className("className"));
driver.findElements(By.cssSelector(".className"));
driver.findElements(By.id("elementId"));
driver.findElements(By.linkText("linkText"));
driver.findElements(By.name("elementName"));
driver.findElements(By.partialLinkText("partialText"));
driver.findElements(By.tagName("elementTagName"));
driver.findElements(By.xpath("xPath"));
driver.findElementsByClassName("className");
driver.findElementsByCssSelector(".className");
driver.findElementsById("elementId");
driver.findElementsByLinkText("linkText");
driver.findElementsByName("elementName");
driver.findElementsByPartialLinkText("partialText");
driver.findElementsByTagName("elementTagName");
driver.findElementsByXPath("xPath");
Timeout Parameters
Java only
The parameters received in Timeout
have switched from expecting (long time, TimeUnit
unit) to expect (Duration
duration).
- Selenium 4
- Legacy
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
driver.manage().timeouts().scriptTimeout(Duration.ofMinutes(2));
driver.manage().timeouts().pageLoadTimeout(Duration.ofSeconds(10));
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.manage().timeouts().setScriptTimeout(2, TimeUnit.MINUTES);
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
Wait Parameters
Waits are also expecting different parameters now. WebDriverWait
is now expecting a Duration instead of a long for timeout in seconds and milliseconds. The withTimeout
and pollingEvery
utility methods from FluentWait
have switched from expecting (long time, TimeUnit
unit) to expect (Duration
duration).
- Selenium 4
- Legacy
new WebDriverWait(driver, Duration.ofSeconds(3))
.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#id")));
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(Duration.ofSeconds(30))
.pollingEvery(Duration.ofSeconds(5))
.ignoring(NoSuchElementException.class);
new WebDriverWait(driver, 3)
.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#id")));
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
Merging Capabilities
Prior to Selenium 4, you could merge one set of capabilities into different set, and this would mutate the calling object. With Selenium 4, this is deprecated; you'll need to manually assign the result of the merge operation.
- Selenium 4
- Legacy
MutableCapabilities capabilities = new MutableCapabilities();
capabilities.setCapability("platformVersion", "Windows 10");
FirefoxOptions options = new FirefoxOptions();
options.setHeadless(true);
options = options.merge(capabilities);
MutableCapabilities capabilities = new MutableCapabilities();
capabilities.setCapability("platformVersion", "Windows 10");
FirefoxOptions options = new FirefoxOptions();
options.setHeadless(true);
options.merge(capabilities);
options
object was getting modified.Firefox Legacy
Before GeckoDriver was around, the Selenium project had a driver implementation to automate Firefox versions below 48. With the release of Selenium 4, this implementation is not needed anymore, as it does not work in recent versions of Firefox.
To avoid major issues when upgrading to Selenium 4, the setLegacy
option will be shown as deprecated. We recommend
relying only on GeckoDriver, rather than using the old implementation.
The following code will show the setLegacy
line deprecated after upgrading.
FirefoxOptions options = new FirefoxOptions();
options.setLegacy(true);
Browser Interface
With Selenium 4, the BrowserType
interface will be deprecated and replaced by the new Browser
interface.
- Selenium 4
- Legacy
MutableCapabilities capabilities = new MutableCapabilities();
capabilities.setCapability("browserVersion", "92");
capabilities.setCapability("browserName", Browser.FIREFOX);
MutableCapabilities capabilities = new MutableCapabilities();
capabilities.setCapability("browserVersion", "92");
capabilities.setCapability("browserName", BrowserType.FIREFOX);
AddAdditionalOption
C# only
The AddAdditionalCapability
capability is deprecated in Selenium 4. Instead, we recommend using AddAdditionalOption
.
- Selenium 4
- Legacy
var browserOptions = new ChromeOptions();
browserOptions.PlatformName = "Windows 10";
browserOptions.BrowserVersion = "latest";
var sauceOptions = new Dictionary<string, object>();
browserOptions.AddAdditionalOption("sauce:options", sauceOptions);
var browserOptions = new ChromeOptions();
browserOptions.PlatformName = "Windows 10";
browserOptions.BrowserVersion = "latest";
var sauceOptions = new Dictionary<string, object>();
browserOptions.AddAdditionalCapability("sauce:options", sauceOptions, true);
More Information
Comprehensive Guide to S4
See Sauce Labs | A Comprehensive Guide to Selenium 4.
Frequently Asked Questions
See Frequently Asked Questions About Selenium 4.