Skip to main content

Make Selenium Tests Run Faster

Learn how to speed up your slow-performing Selenium tests.

Issue

Tests running on BrowserStack Automate slows down with the error as shown in the following image:

keep-alive missing issue in Automate

Cause

The absence of the keep-alive parameter leads to slow-performing tests. When you don’t use this parameter, your client binding is using a new request every time you communicate with BrowserStack.

Why you must mitigate this issue

As an organization, optimizing your builds to run faster, is crucial. BrowserStack understands the need to identify issues that might not be evident, but have a large impact on the speed and stability of your test sessions.

Use the resolutions provided to mitigate these issues so as to:

  • Improve performance
  • Reduce test flakiness

Resolution/Workaround

When you use the keep-alive parameter, it sets a 30 seconds timeout after which the connection times out.

To fix this warning, use the keep-alive parameter in your test script. Moreover, using the keep-alive parameter makes your client binding use the same connection for every request, which eventually speeds up your tests.

Refer to the following code snippets to learn how to use the keep-alive parameter in your test script:

Note: The keep-alive parameter for Java and C# languages is enabled by default. If you’re using these languages and still encounter the HTTP keep-alive missing error, contact the Support team.

In your Node.js project or any other Node.js based framework’s project such as WebdriverIO, NightwatchJS, etc., do the following:

  1. Create a file named fast-selenium.js in the folder where your test script file is located
  2. Add the code given below to the fast-selenium.js file
var http = require('http'),
    https = require('https');

//set the time (in seconds) for connection to be alive
var keepAliveTimeout = 30*1000;

if(http.globalAgent && http.globalAgent.hasOwnProperty('keepAlive')) {
    http.globalAgent.keepAlive = true;
    https.globalAgent.keepAlive = true;
    http.globalAgent.keepAliveMsecs = keepAliveTimeout;
    https.globalAgent.keepAliveMsecs = keepAliveTimeout;
} else {
    var agent = new http.Agent({
        keepAlive: true,
        keepAliveMsecs: keepAliveTimeout
    });

    var secureAgent = new https.Agent({
        keepAlive: true,
        keepAliveMsecs: keepAliveTimeout
    });

    var httpRequest = http.request;
    var httpsRequest = https.request;

    http.request = function(options, callback){
        if(options.protocol == "https:"){
            options["agent"] = secureAgent;
            return httpsRequest(options, callback);
        }
        else {
            options["agent"] = agent;
            return httpRequest(options, callback);
        }
    };
}

Edit your existing test script to add the following require statement that imports the fast-selenium.js file:

require('./fast-selenium.js');

Here is a sample test script that uses the fast-selenium.js file to perform a test case:

require('./fast-selenium.js'); // imports the fast-selenium script
  
const webdriver = require('selenium-webdriver');
// Input capabilities
const capabilities = {
 'device' : 'Samsung Galaxy S21 Plus',
 'realMobile' : 'true',
 'os_version' : '11.0',
 'browserName' : 'Android',
 'name': 'BStack-[NodeJS] Sample Test', // test name
 'build': 'BStack Sample Build' // CI/CD job or build name
}
async function runTestWithCaps () {
  let driver = new webdriver.Builder()
    .usingServer('http://YOUR_USERNAME:YOUR_ACCESS_KEY@hub-cloud.browserstack.com/wd/hub')
    .withCapabilities(capabilities)
    .build();
  await driver.get("https://bstackdemo.com/");
 
  try {
    await driver.wait(webdriver.until.titleMatches(/StackDemo/i), 5000);
    await driver.executeScript(
      'browserstack_executor: {"action": "setSessionStatus", "arguments": {"status":"passed","reason": "Title matches to StackDemo!"}}'
    );
  } catch (e) {
    await driver.executeScript(
      'browserstack_executor: {"action": "setSessionStatus", "arguments": {"status":"failed","reason": "​​Title does not match to StackDemo"}}'
    );
  }
  await driver.quit();
}
runTestWithCaps(); 

In your test script, when initializing the driver, use the keep_alive parameter and set it to True, as shown in the following code snippet.:

driver = webdriver.Remote(
    command_executor='https://YOUR_USERNAME:YOUR_ACCESS_KEY@hub-cloud.browserstack.com/wd/hub',
    desired_capabilities=desired_cap, keep_alive=True)

Here is a sample test script that uses the keep_alive parameter to perform a test case:

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
desired_cap = {
 'browserName': 'iPhone',
 'device': 'iPhone 12 Pro Max',
 'realMobile': 'true',
 'os_version': '14',
 'name': 'BStack-[Python] Sample Test', # test name
 'build': 'BStack Sample Build' # CI/CD job or build name
}
driver = webdriver.Remote(
    command_executor='https://YOUR_USERNAME:YOUR_ACCESS_KEY@hub-cloud.browserstack.com/wd/hub',
    desired_capabilities=desired_cap, keep_alive=True)
      
driver.get("https://bstackdemo.com/")
try:
    WebDriverWait(driver, 5).until(EC.title_contains("StackDemo"))
    # Setting the status of test as 'passed' or 'failed' based on the condition; if title of the web page starts with 'StackDemo'
    driver.execute_script('browserstack_executor: {"action": "setSessionStatus", "arguments": {"status":"passed", "reason": "Title contains StackDemo!"}}')
except TimeoutException:
    driver.execute_script('browserstack_executor: {"action": "setSessionStatus", "arguments": {"status":"failed", "reason": "​​Title does not contain StackDemo."}}')
driver.quit() 

In your Ruby project, create a file named fast-selenium.rb in the folder where you test script file is located. Copy the following code to the file you created:

require 'selenium/webdriver/remote/http/curb'

module Selenium
  module WebDriver
    module Remote
      class Bridge
        attr_accessor :http_curb
        def http
          unless @http_curb
            @http_curb = Http::Curb.new
            @http_curb.server_url = @http.send(:server_url)
          end
          @http_curb
        end
      end # Bridge
    end # Remote
  end # WebDriver
end # Selenium

Edit your existing test script to add the following require statement that imports the fast-selenium.rb file:

require './fast-selenium'

Here is a sample test script that uses the fast-selenium.rb file to perform a test case:

require 'rubygems'
require 'selenium-webdriver'
require './fast-selenium'
  
# Input capabilities
caps = Selenium::WebDriver::Remote::Capabilities.new
caps['device'] = 'iPhone 12 Pro Max'
caps['realMobile'] = 'true'
caps['os_version'] = '14'
caps['javascriptEnabled'] = 'true'
caps['name'] = 'BStack-[Ruby] Sample Test' # test name
caps['build'] = 'BStack Sample Build' # CI/CD job or build name
driver = Selenium::WebDriver.for(:remote,
  :url => "https://YOUR_USERNAME:YOUR_ACCESS_KEY@hub-cloud.browserstack.com/wd/hub",
  :desired_capabilities => caps)
    
# Opening demo website
driver.navigate.to "https://bstackdemo.com/"
wait = Selenium::WebDriver::Wait.new(:timeout => 5) # seconds
begin
  wait.until { !driver.title.match(/StackDemo/i).nil? }
  driver.execute_script('browserstack_executor: {"action": "setSessionStatus", "arguments": {"status":"passed", "reason": "Title matches to StackDemo!"}}')
rescue
  driver.execute_script('browserstack_executor: {"action": "setSessionStatus", "arguments": {"status":"failed", "reason": "Title does not matches to StackDemo"}}')
end
driver.quit

We're sorry to hear that. Please share your feedback so we can do better

Contact our Support team for immediate help while we work on improving our docs.

We're continuously improving our docs. We'd love to know what you liked






Thank you for your valuable feedback

Is this page helping you?

Yes
No

We're sorry to hear that. Please share your feedback so we can do better

Contact our Support team for immediate help while we work on improving our docs.

We're continuously improving our docs. We'd love to know what you liked






Thank you for your valuable feedback!

Talk to an Expert
Talk to an Expert