The Selenium browser automation tool allows you to write test code that runs through all the possible actions in your web app faster and more effectively that manual testing. This section of the Sauce Labs documentation provides an overview of how to use Selenium with Sauce Labs to achieve efficient and consistent test results to ensure your web app works on every operating system and browser.
What You’ll Need
- A Sauce Labs account (Log in or sign up for a free trial license).
- Your Sauce Labs Username.
- A working development environment for one of the supported Selenium languages: Java, C#, Python, or Ruby.
Selenium is built on a client-server architecture, which includes both client and server components.
The current API used by Selenium servers and browser drivers is defined in the W3C WebDriver specification and communicated between the components using http commands.
- The client code, specifically the Remote WebDriver class contains the methods that implement the API for automating the browser. Selenium translates this code into the https commands defined by the W3C, and sends this information to a server.
- The Selenium Server receives the http commands that were sent by the Selenium client. This server can be in standalone mode, or in a grid mode with different servers set as hubs and nodes. The server forwards the commands to the browser driver, which ultimately controls how the browser is automated.
For Sauce Labs, it looks like this:
Seven Steps of Selenium Tests
There are seven basic elements of a Selenium test script, which apply to any test case and any app under test (AUT):
- Create a WebDriver session.
- Navigate to a Web page.
- Locate an HTML element on the Web page.
- Perform an action on the located element.
- Assert the performed action did the correct thing.
- Report the result of the assertion.
- End the session.
The following sections walk through each of these steps using a basic test case example — logging into a website. This example ensures that a specific user can successfully log into our demo site, Swag Labs.
Step 1: Create a Remote Session
Create an instance of Selenium's Remote WebDriver class so you can invoke methods of the Selenium WebDriver API on Sauce Labs infrastructure.
Direct Tests to Sauce Labs
Remote WebDriver classes are instantiated with the URL of the server or service you want for your tests. For Sauce Labs, choose a URL from our Data Center Endpoints.
The way to define capabilities in recent versions of Selenium is with browser options classes. These classes are designed to ensure users have W3C WebDriver-compliant capabilities. The configurations set on these classes do one of two things:
- Ensure you have the session you want (e.g., browser name, browser version, operating system).
- Set the behavior you want in your session. There are three types of options that set behavior:
Selenium has moved away from "Desired Capabilities" classes to Browser Options classes. Some of the functionality in the old classes has been deprecated or removed for Selenium 4.0.
The following example shows the instantiation of a Sauce Labs session with a driver object instance, using authentication values and the OS/Browser targets for a test written in Selenium 4.0:
Use Credential Environment Variables
Set your Sauce Labs account credentials as environment variables rather than hard-coding them into all your scripts for efficiency and to protect them from unintended exposure.
Step 2: Navigate to a Web Page
get method on your WedDriver instance, using the variable name you assigned, and pass the URL of the web page containing the element you wish to test as an argument. The following gets our Swag Labs login page:
For more information, see the Selenium documentation on Browser Navigation.
Step 3: Locate an HTML Element on a Web Page
Once the test script accesses the page to test, it needs to find the elements that an end user would interact with. In this case, the Login text fields and Submit button.
To find an element, we need to right-click on the elements we are interested in and select Inspect from the context menu. The form elements look like this:
<input class="input_error form_input" placeholder="Username" type="text" data-test="username" id="user-name" name="user-name" autocorrect="off" autocapitalize="none" value="">
<input class="input_error form_input" placeholder="Password" type="password" data-test="password" id="password" name="password" autocorrect="off" autocapitalize="none" value="">
<input type="submit" class="submit-button btn_action" data-test="login-button" id="login-button" name="login-button" value="Login">
Selenium provides multiple element selection strategies, which include identifying an element by:
- A specific attribute value, such as the value of
- The tag name of the element, such as
- Visible text; this only applies to anchor elements, such as
<a href="https://www.saucelabs.com">Sauce Labs</a>.
- A CSS selector,
- An XPath expression, such as
Identifying Elements in HTML
Learn to use CSS Selectors! Selenium 4.0 converts most of the supported selectors into CSS, so there isn't a good reason to use anything else!
Most of the elements in our Swag Labs example have multiple unique attributes that make it easy to identify them with CSS.
For more information, see the Selenium documentation on Locating Elements.
To find an element, pass your locator method as an argument of a WebDriver API finder method.
The find element method for the given language will search the DOM (Document Object Model) of the current web page until it finds a matching element and returns it.
Regardless of the language, changing the method name from "element" to "elements" will search the entire DOM, and return a collection of all matching elements rather than just the first one.
The following example invokes the finder method on the driver instance to locate the elements for which we defined locators in the last section:
For more information, see the Selenium documentation on the Find Element.
Synchronization is an advanced topic, but it is essential when locating an element that the app is ready for the element to be located. There are two docs-1.1 approaches to synchronization: implicit and explicit.
When Selenium executes a find element call and the driver can not find the element, an exception is thrown immediately. An implicit wait is set telling the driver how long to wait before throwing the exception. If the element is located right away, the value of the implicit wait does not matter.
Do not use implicit waits! While it is a one-line code change that can potentially reduce the number of failed tests in your suite, it is more of a crutch than a successful long term solution. Tests run on Sauce Labs that set an implicit wait are more likely to be reported as failing than tests that do not set implicit waits. If you're in a bind, and want to try an implicit wait, make it a small value, set it with the Browser Options when creating the session, and then don't change it.
An explicit wait handles the synchronization in the code itself, typically with some form of while loop. When the desired condition is met, the test can continue, and only if the condition is not met after the maximum wait time will the code throw an exception.
Do Not Mix Explicit and Implicit Waits
Mixing implicit and explicit waits can cause unpredictable outcomes, which is another reason to avoid implicit waits.
Each language implements this slightly differently. Java and Python have Expected Conditions classes, but the recommended approach in all languages at this point is to use a lambda expression, like so:
For more information, see the Selenium documentation on Waits.
Step 4: Perform Actions on Located Elements
Invoke an interaction method on an instance of the WebElement interface to simulate the user's interaction with the website elements you have located. The basic interactions include:
- The "send keys" method to enter text into an input field
- The "clear" method to clear entered text from an input field
- The "click" method to simulate a mouse down action on any element
- The "submit" method will submit a form
The "submit" method does not accurately simulate how a user would submit the form, so it is recommended to click the Submit button instead.
The following example automates a user login by sending keys to the username and password text fields, and clicking the Submit button:
Step 5: Assert a Result
You can not have a test without an assertion. Each test should have something specific it is validating and have at least one explicit line of code to ensure that this functionality is working as intended. What makes a test successful and how to evaluate success requires docs-1.1 knowledge and can be more art than science.
Step 6: Report the Results
Keeping track of the success and failure of your tests is essential for identifying problems. Testers record their results in various ways and with various amounts of information. Sauce Labs is a good resource for recording failures because with the videos and screenshots and logs it is much easier to determine the reason for the failures.
To see your results on Sauce Labs, navigate to the AUTOMATED > Test Results page, where you can watch your test run live or review the video or screenshot assets of the test.
This will vary based on test runner, but here's an example with JUnit 5:
Step 7: End the Session
It is important to remember to close the browser when you are done with it by calling the quit method on the Remote WebDriver instance.
- quits the browser, closing all windows.
- ends the Sauce session allowing timely processing of results and storage of artifacts.
The following examples invokes the quit method on the driver variable:
A great way to minimize complexity and reduce boilerplate code for writing Selenium tests with Sauce Labs is to use the Sauce Bindings.
Compare these equivalent Java implementations:
Click here to see the complete Java example of the above steps.
Click here to see the equivalent code using the Sauce Bindings JUnit 5 Test Runner Library.
The example is a simple one, and only creating a number of files just like it one would not be very efficient.
Scaling up tests requires at a minimum a test runner, and even better a more fully featured testing library. These tools allow for better abstractions and less code duplication in your tests, as well as the ability to run tests in parallel instead of just sequentially.
Test Runners include:
- Java - JUnit 5, JUnit 4, TestNG
- Python - pyTest, unittest
- Ruby - RSpec, Cucumber
- .NET - NUnit, MSTest
Testing Libraries include:
- Java - Selenide, FluentLenium, QAF
- Python - Nerodia, Helium, SeleniumBase
- Ruby - Capybara, Watir
The Sauce Labs Training Repo contains an extensive selection of demonstration scripts illustrating parallel testing in different frameworks and programming language combinations.