Skip to end of metadata
Go to start of metadata

Sauce Labs is a cloud platform for executing automated and manual mobile and web tests. Sauce Labs supports running automated tests with Selenium WebDriver (for web applications) and Appium (for native and mobile web applications). This topic will provide you with an example of how to get your Ruby tests up and running on Sauce.

Example Only

The code in this topic is presented as an example only, since your tests and testing environments may require specialized scripting. This information should be taken only as an illustration of how you could set up your tests with Sauce Labs, and is not directly supported by Sauce.

Prerequisites

Code Example

This Ruby example script executes a simple test to open a browser, navigate to the Sauce Labs demo web app, and then close the browser. It also incorporate a number of best practices, such as using environment variables for authentication credentials, and is set up to use RSpec to report Pass/Fail results to your Sauce Labs dashboard. You can clone this script directly from the saucelabs-training GitHub repo and modify it as you want to test your authentication credentials, set desired capabilities, and run tests against your own web app. 
 Click here to view the example script

require "selenium-webdriver"
require "rspec"
require "sauce_whisk"

describe "Instant_RSpec_Test4" do
  before(:each) do |test|
    caps = {
        browser_name: 'chrome',
        platform_name: 'windows 10',
        browser_version: '71.0',
        "goog:chromeOptions" => {w3c: true},
        "sauce:options" => {
            name: test.full_description,
            seleniumVersion: '3.141.59',
            username: ENV['SAUCE_USERNAME'],
            accessKey: ENV['SAUCE_ACCESS_KEY'],
            # best practices involve setting a build number for version control
            build: 'build-0.0.1',
            # tags to filter test reporting.
            tags: ['instant-sauce', 'ruby-rspec', 'module4'],
            # setting sauce-runner specific parameters such as timeouts helps
            # manage test execution speed.
            maxDuration: 1800,
            commandTimeout: 300,
            idleTimeout: 1000
        }
    }
    @driver = Selenium::WebDriver.for(:remote,
                                      url: 'https://ondemand.saucelabs.com:443/wd/hub',
                                      desired_capabilities: caps)
  end
  it "should_open_chrome" do
    @driver.get('https://www.saucedemo.com')
    puts "title of webpage is: #{@driver.title}"
  end
  after(:each) do |example|
    SauceWhisk::Jobs.change_status(@driver.session_id, !example.exception)
    @driver.quit
  end
end

Running the Example Test

  1. Copy the example code and save it into a file called simple.rb.
  2. Open a command line terminal and navigate to the file location. 
  3. Run simple.rb.

    ruby simple.rb

    Voila! You have just run your first test on Sauce, which you can verify by checking your Dashboard.

Analyzing the Code

A closer look at the code sample will help you understand how you could use it as the basis for setting up your own tests from scratch, or how you can set up existing tests to run in the Sauce cloud. 

Set Sauce URL and Access Credentials

If you wanted to run a Selenium test on Selenium locally, you would initiate a driver for the browser you want to test against like this.

Local Ruby Test Example
driver = Selenium::WebDriver.for :firefox 

To run a test on a remote service like Sauce Labs, all you need to change is your driver definition, and make sure that the sauce_endpoint variable includes your Sauce USERNAME and ACCESSKEY.

Remote Ruby Test on Sauce Example
driver = Selenium::WebDriver.for :remote, :url => sauce_endpoint, :desired_capabilities => caps
sauce_endpoint = "http://YOUR_SAUCE_USERNAME:YOUR_SAUCE_ACCESSKEY@ondemand.saucelabs.com:80/wd/hub"

To find your Sauce Labs access key:

  1. Sign in to https://saucelabs.com with the username you set up when you created your account. 
    You will use this same username in your test script. 
  2. To find your access key:
    1. Click your name in the Account Profile menu in the upper-right corner.
    2. Click User Settings.
    3. Scroll down to Access Key and click Show.
    4. Enter the password you use to sign in to Sauce Labs to view the access key.
    5. Click the Copy icon.


IP Ranges and Data Center Endpoints
Sauce Labs has data centers in both the US and EU. You can access Sauce Labs services from either location by providing the appropriate URL endpoints, and whitelisting their associated IP ranges. 

 US Data Center

Virtual Device Cloud: https://ondemand.saucelabs.com/wd/hub
Sauce Connect Proxy: https://saucelabs.com/rest
REST API:  https://saucelabs.com/rest/v1
IP Ranges:

162.222.72.0/21 (this is equivalent to the range 162.222.72.1 – 162.222.79.254)
66.85.48.0/21 (this is equivalent to the range 66.85.48.0 - 66.85.55.255)

Set Desired Capabiliites

Once you have your tests set up to run in the Sauce cloud, you need to define the platform, browser, and version you want the test to run against, which is where :desired_capabilites and caps come into play. 

caps = { :platform => "Mac OS X 10.9", :browserName => "Chrome", :version => "31" }

You can manually enter the values you want for :platform:browsername, and :version, or you can use the handy Platform Configurator to generate the caps values for any combination of platform, browser, and browser version. 

Running Local Tests

Developing websites/apps within your local network is secure and efficient. The drawback to this method is that local assets are not publicly-accessible on the Internet, so the browsers/devices in the Sauce Labs cloud can't load and test your app. The solution is to use Sauce ConnectSauce Connect is a proxy server that creates a secure tunnel connection between the Sauce Labs virtual machine that runs your test and your local  network. You can also use Sauce Connect to test applications and websites that are located within your corporate firewall. Sauce Connect is not required to run tests on Sauce Labs, only in situations where the application or website you want to test is not publicly accessible. 

Running Tests in Parallel

For more information, check out the example scripts in our GitHub repo

Now that you’re running tests on Sauce, you may wonder how you can run your tests faster. One way to increase speed is by running tests in parallel across multiple virtual machines.

You can run your tests in parallel at two levels, and you can run your tests in parallel across multiple browsers. For example, if you have 10 tests and want to run on five browsers, this would be parallelism of five. You can also run tests across browsers and each test in parallel. Using our previous example this would be more like 50 parallel tests. Doing this requires that your tests are written in a way that they do not collide with one another, as described in our Best Practice topics avoiding external test dependencies and avoiding dependencies between tests.

Match Thread Count to Concurrency Limit

You should match your thread count to your concurrency limit, which is shown in the My Account section of your user profile information on the Sauce Labs dashboard.  

There are many ways you could run tests in parallel with Ruby, but this example will use RSpec, the behavior-driven development (BDD) framework for Ruby. 
  1. Add the RSpec and ParallelTests gems into your Gemfile, then run bundle install.

    gem "rspec", "~> 3.0.0"
    gem "parallel_tests", "~> 1.6.1
  2. Create a spec directory in your project's root directory.
  3. In the spec directory, create a file called sauce_driver.rb, which will encapsulate the behaviour we need to create Selenium drivers with Sauce Labs.

    You can also clone this file directly from GitHub.

    require "selenium/webdriver"
    
    module SauceDriver
      class << self
        def sauce_endpoint
          "https://YOUR_SAUCE_USERNAME:YOUR_SAUCE_ACCESS_KEY@ondemand.saucelabs.com:443/wd/hub"
        end
    
        def caps
          caps = {
            :platform => "Mac OS X 10.9",
            :browserName => "Chrome",
            :version => "31"
          }
        end
    
        def new_driver
          Selenium::WebDriver.for :remote, :url => sauce_endpoint, :desired_capabilities => caps
        end
      end
    end

     

    Now you need to make RSpec create a new driver for each spec. The cleanest way to do this is by defining an around hook, which will be run, naturally, around every spec. 

  4. Create a file in the spec directory called spec_helper.rb
    This file will be require `d by every spec you create, as this is where, by convention, any setup code is placed.

    You can also clone this file directly from GitHub.

    require "rspec"
    require_relative "sauce_driver"
     
    RSpec.configure do |config|
      config.around(:example, :run_on_sauce => true) do |example|
        @driver = SauceDriver.new_driver
        begin
          example.run
        ensure
          @driver.quit
        end
      end
    end

    On line 5 you set up a new block of code to be run around every example tagged with :run_on_sauce => true. This lets you have non-Selenium tests that don't spin up Selenium sessions. You have to make sure you include :run_on_sauce on all your Selenium tests, though!

    On line 6 you use the SauceDriver class you set up earlier to create a new Selenium driver, 'pointed' at Sauce Labs. Then, on line 8, you run the example. On lines 9 - 11 we call quit on the Selenium session; This is done in an ensure block so that each test always closes off its driver, even if something goes wrong.

Now you have RSpec set up to create drivers and close them down. Your next question might be, "How do I use these drivers?" Super simple. Because driver is an instance variable, and the around block runs in the context of the spec, it can use the driver directly. Consider this example spec.

You can also clone this file directly from GitHub.

require_relative "spec_helper"
 
describe "Google's Search Functionality" do
  it "can find search results", :run_on_sauce => true do
    @driver.manage.timeouts.implicit_wait = 10
    @driver.navigate.to "http://www.google.com"
 
    raise "Unable to load Google." unless @driver.title.include? "Google"
 
    query = @driver.find_element :name, "q"
    query.send_keys "Sauce Labs"
    query.submit
 
    puts @driver.title
  end
end

On line 1 you require spec_helper. Then, on line 4 you add :run_on_sauce => true to make sure the around block runs. You can use the created driver, @driver, without any further setup, and you don't have to do anything to close it off either. This means you're much less likely to forget to do so when you write more tests.

Now, parallel testing! If you go ahead and create some more specs like this one (you can copy google_spec.rb into other files in the spec directory, just make sure the filenames end in spec.rb), then run the specs from your project root directory with:

bundle exec parallel_rspec -n 2 spec/

You should be able to log into Sauce Labs and see your tests running in parallel. If your account has more than two concurrency slots (meaning, you have a paid account), you can increase the number after -n to match your concurrency, and parallel_tests will spin up more tests at once.

Reporting Test Results

Selenium is a protocol focused on automating the actions of a browser, and as such, it doesn't encompass the notions of a "test" that "passes" or "fails." Sauce Labs lets you notify us of test status using our REST API. All you need is the ID Sauce Labs gave the job, and the status your test ended with. Then, you can use the Update Job method on the REST API to set the job's status.

The Job ID is the simplest part of the process. The ID assigned to each job by Sauce Labs is the same as the Session ID for the corresponding Selenium session, which you can pull off the driver like so:

job_id = driver.session_id 

Using the REST API is best done with the sauce_whisk gem, which assumes you've set your Sauce username and access key as the SAUCE_USERNAME and SAUCE_ACCESS_KEY environment variables.

This example shows how you would modify the example RSpec spec_helper.rb file to check the status of the test, and pass that to the REST API.

Modifying spec_helper.rb to Report Test Results to the Dashboard Using the sauce-whisk Gem
require "sauce_whisk"

RSpec.configure do |config|
  config.around(:example, :run_on_sauce => true) do |example|
    @driver = SauceDriver.new_driver
    @job_id = @driver.session_id
    begin
      example.run
    ensure
      SauceWhisk::Jobs.change_status job_id, !example.exception.nil?
      @driver.quit
    end
  end
end 

That's it! Your tests will now be reporting their status to the Sauce Labs REST API.