Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save brianjbayer/81be6b7c8196d8c9a16e94d629f63f0d to your computer and use it in GitHub Desktop.
Save brianjbayer/81be6b7c8196d8c9a16e94d629f63f0d to your computer and use it in GitHub Desktop.
Add running your Ruby RSpec or Cucumber browser tests in parallel natively and in docker compose

Run Your Ruby RSpec or Cucumber Browser Tests in Parallel in Docker Compose

citzenM Chicago - Brian J Bayer


This shows you how to add running your Ruby RSpec or Cucumber browser tests in parallel natively (macOS) and in your docker compose framework.

You will...

  1. Add the parallel_tests gem

  2. Configure your default Rake task to run in parallel (except Safari)

  3. Configure the selenium/standalone browser containers in docker compose

    This may resolve errors like these...

    Selenium::WebDriver::Error::SessionNotCreatedError:
      Could not start a new session. No nodes support the capabilities in the request
    

Add the parallel_tests Gem

You will need to add the parallel_tests gem to your project.

  1. Add the parallel_tests gem to your Gemfile

    gem 'parallel_tests'
  2. Install the parallel_tests gem (in your containerized development environment)

    bundle install

Safari Does Not Support Running in Parallel

🍎 Safari does not support running in parallel on a single machine.

Running parallel_rspec/parallel_cucumber with Safari as the Selenium browser will result in errors like these...
Selenium::WebDriver::Error::SessionNotCreatedError:
  Could not create a session: The Safari instance is already paired with another WebDriver session.
  

or...

Could not create a session: The session timed out while connecting to a Safari instance.
  (Selenium::WebDriver::Error::SessionNotCreatedError)
  

or even...

Net::ReadTimeout with #<TCPSocket:(closed)> (Net::ReadTimeout)
  

Running In Parallel

You should now be able to run your tests in parallel at least in your native browsers (i.e. Chrome, Firefox, Edge) IF your test framework already supports them.

For RSpec...

To run your tests in parallel in RSpec, use the parallel_rspec command:

bundle exec parallel_rspec

For Ruby Cucumber...

To run your tests in parallel in Ruby Cucumber, use the parallel_cucumber command:

bundle exec parallel_cucumber

πŸ“– Use the -h option to see all options

Configure Your Default Rake Task to Run in Parallel

After the parallel_tests gem has been added to your project, you can configure your default Rake task to run your tests in parallel.

🍎 These examples of custom Rake tasks include logic for running the tests sequentially when the BROWSER environment variable is set to 'safari'. You can omit or modify this as needed.

Require the parallel_tests Rake Tasks

Require the parallel_tests/tasks rake tasks in your Rakefile

require 'parallel_tests/tasks'

Configure RSpec Rake Tasks

To configure your default Rake task to run your RSpec tests in parallel...

  1. Add the parallel rspec rake task to your Rakefile

    πŸ‘€ This assumes the browser is specified in the BROWSER environment variable

    # Cucumber Tasks
    Cucumber::Rake::Task.new(:cucumber) do |t|
      t.profile = 'default'
    end
    
    namespace :rspec do
      desc 'Run RSpec in parallel using parallel_tests'
      task :parallel do
        if ENV['BROWSER'] == 'safari'
          warn 'rake: running specs SEQUENTIALLY for safari'
          RSpec::Core::RakeTask.new(:spec)
          Rake::Task['spec'].invoke
        else
          Rake::Task['parallel:spec'].invoke
        end
      end
    end

    This adds the rake tasks...

    • rake rspec:parallel
  2. Make the parallel rspec rake task your default

    # Set the Default to running in parallel
    task default: 'rspec:parallel'

πŸ“– Here is an example in a Rakefile


Configure Ruby Cucumber Rake Tasks

To configure your default Rake task to run your cucumber tests in parallel...

  1. Add the parallel cucumber rake tasks to your Rakefile

    πŸ‘€ This assumes the browser is specified in the BROWSER environment variable

    # Cucumber Tasks
    Cucumber::Rake::Task.new(:cucumber) do |t|
      t.profile = 'default'
    end
    
    namespace :cucumber do
      desc 'Run Cucumber features in parallel using parallel_tests'
      task :parallel do
        if ENV['BROWSER'] == 'safari'
          warn 'rake: running specs SEQUENTIALLY for safari'
          Rake::Task[:cucumber].invoke
        else
          Rake::Task['parallel:features'].invoke
        end
      end
    end

    This adds the rake tasks...

    • rake cucumber
    • rake cucumber:parallel
  2. Make the parallel cucumber rake task your default

    # Set the Default to running in parallel
    task default: 'cucumber:parallel'

πŸ“– Here is an example in a Rakefile


Configure the Selenium Standalone Browser Containers in Docker Compose

If your project is already using docker or docker compose with the selenium/standalone images as your browser, you may need to modify your configuration in order to run your tests in parallel.

You should not need to use the selenium grid (images) unless you are running a high amount of parallelization requiring multiple host machines

This may resolve Selenium::WebDriver::Errors like these...
Selenium::WebDriver::Error::SessionNotCreatedError:
  Could not start a new session. No nodes support the capabilities in the request
  

⏱️ As with all performance-based settings, these settings will depend on your host machine running the selenium/standalone container and your parallel level.

This shows a simple example where the parallel level is 2.

Set the Standalone Container's SE_NODE_MAX_SESSIONS Environment Variable

You must set the SE_NODE_MAX_SESSIONS environment variable of the selenium/standalone container to support multiple browser sessions.

environment:
  # The number of browser sessions should correspond to parallelism
  - SE_NODE_MAX_SESSIONS=2

Adjust the Standalone Container's shm_size

You may need to also adjust the selenium/standalone- container's shm_size setting or change how it is handled.

shm_size: 4gb

A Docker Compose Example

Here is a full example in docker compose...

services:
  seleniumbrowser:
    # The selenium/standalone-chromium image is multiplatform (arm64)
    image: ${SELENIUM_IMAGE:-selenium/standalone-chromium:latest}
    platform: ${SELENIUM_IMAGE_PLATFORM:-}
    container_name: ${SELENIUM_HOSTNAME:-seleniumbrowser}
    # shm size should be considered with parallelism
    shm_size: 4gb
    volumes:
      - /dev/shm:/dev/shm
    ports:
      - "5900:5900"
      - "7900:7900"
    environment:
      # The number of browser sessions should correspond to parallelism
      - SE_NODE_MAX_SESSIONS=2
    healthcheck:
      test: ["CMD-SHELL", '/opt/bin/check-grid.sh --host 0.0.0.0 --port 4444']
      interval: 15s
      timeout: 30s
      retries: 5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment