Selenium Server Setup

Why Selenium Server (aka Grid)?

If one were to run their tests back to back it would take some time to deliver the final result of all tests.  Say you had 100 browser automation tests.  Let’s further say that each test takes on average 2min to complete.  Back to back that’s 200min.  That’s about 3.3 hours to complete your automated testing.

However, if you farmed your 100 tests against 100 browsers across multiple VM’s you would have a result across all tests in 2min – because all the tests are run in parallel and in isolation to each other.  You could que the tests  across 25 browsers, and still the resulting time for full test completion would be under 20min.

How Selenium Server Works

Selenium server (previously called Grid) is a master/slave relationship.  They call the master the “hub” and the slave a “node.”  The hub is stood up someplace and listens for other machines/vm’s to register with it.  As each machine registers it will be listed in the Selenium Server Console – which is a webpage showing each connection that has registered with the hub – it will also show what browsers each connection is supporting.

If the node doesn’t specify any specific configuration (i.e. which browsers to run), then it will default with 5 versions of each browser installed on the box (IE, Firefox and Chrome, for example.)  It will attempt to run up to 5 browsers each on a single machine/VM. That may be problematic, and you can tune how many browsers to support per VM, as well as which browsers to support.  More on that in the details that follow.

Organizing Tests

When you farm tests to Selenium Server, you must pass tests in a group.  Each group is sent to a respective node (slave.)

Sometimes people put all their tests in one file and send that file to the Selenium Server.  But it runs the tests sequentially.  Why?  Because Selenium Server can’t break apart a file and know what to pass to the nodes.  It instead will farm each request it gets to a specific server. If all tests are in one request, then the tests will not run in parallel.  If you break your requests up and pass them to the Selenium Server all at once, then the server will take each request and farm it to the available nodes.

I like to use Cucumber.  Cucumber will organize tests into files called features.  Each feature file is a set of tests that cover specific functionality.  For example, let’s say you had 10 tests that cover functionality for your homepage.  They would be put in one file perhaps called homepage.feature.  Then you may have 20 tests for “login” in a login.feature file.  If you then send both files to Selenium Server, it will process them and send one set of tests (homepage.feature) to VM #1 and the login tests to VM #2.  See how that works?

You may use something other then Cucumber.  Perhaps you write your tests in flat ruby, groovy or python files.  That’s fine, just break them up into multiple files.  Each file can then be sent to the Selenium Server, which will farm them to the appropriate nodes – all running in parallel.

Selenium, Watir, Capybara, Webdriver

Another question that comes up is, “Does it matter if I use Watir Webdriver or Capybara? Can I still send it to the Selenium Server?”  It doesn’t matter.  Under the hood all those frameworks are using Selenium.  They’re just wrappers to the Selenium Core.

Setting Up Selenium Server Hub

It’s actually pretty easy to set Selenium Server up.  You download one file to all your machines, this file will be the latest Selenium Server.  As of this writing, this can be downloaded from:

http://www.seleniumhq.org/download/

Once you have the latest selenium server jar downloaded, you will need to place it somewhere consistent across all your VM’s.  You could drop it at the root of your machine or in some folder.

To manually kick it off, just run:

java -jar [name of your selenium server jar] -role hub

This will start Selenium Server on this machine at port 4444.  Let’s say your machine is called QA1.myserver.com, then you could go to qa1.myserver.com:4444/grid and it should show a page indicating it’s up and running.

Batch File for the Server

Your server that hosts the Selenium Server(s) will probably go down or restart from time to time.  It’s a good idea to make use of the task manager to start your selenium hub in case of restart.

Follow the instructions for your particular OS to start up a command: java -jar [selenium server jar] -role hub for when the machine starts up or restarts.

Setting Up the Selenium Server Node

You use the same jar file that is used for the hub, but you pass in the value “node” for the role.  Example:

java -jar [your selenium server jar file name] -role node -hub [url to your hub]/grid/register

You must have the URL to your hub be accessible. Make sure your  nodes can reach the hub… so if the hub is running on qa1.mydomain.com:4444, then you would start the node with:  -role node -hub http://qa1.mydomain.com:4444/grid/register

Once initiated, review the output in the console.  If there are no errors, then in a browser go to your hub:

http://qa1.mydomain.com:4444/grid/console

The grid console will show all the nodes currently registered with the hub.  It will also show all the browsers being supported.

Special Nodes for Targeted Browsers

You may have nodes running specific operating systems with a specific version of a browser… for example a Windows 8 laptop running IE 11, a Windows 2008 server VM running IE 9, etc.  For Selenium Server to understand what browser and version is running someplace, you will have to set that up with a command line parameter when you start the node.

You pass this on the node command like like so:

java -jar [your selenium jar] -role node -hub http://qa1.mydomain.com:4444/grid/register -browserName=”internet explorer”,version=10

*NOTE: make sure there is no space from the browser and the comma and the word version.  If you have -browserName=”internet explorer”, version=10 you will not connect to the right browser. There can’t be a space there.

The version isn’t really the real version. You might be using version 10.4.  Selenium will just run Internet Explorer. The version is more for labeling.  In your process when you send tests to Selenium Server, you specify the browser and version.  It will tell Selenium Server to run the test on “internet explorer” with version 10.  Then Selenium Server will ask which nodes support IE with version “10.”  Once it finds the node with the correct browser and version it will execute the tests there.

Physical Machines

Some ask if they can have nodes be physical machines. Getting OSX Yosemite in a VM is probably not even legal, due to OSX restrictions on installation.  But you can use a physical OSX device and have it run the same Selenium Server node parameter to connect to the Selenium Server hub – just like above.

Appropriate Webdrivers

Make sure that each node that will be tested has the appropriate webdrivers.  These drivers will need to be on a path.  I typically create folder called “webdrivers” and put them all there.  Then I add that folder to the system PATH. Once on the path (if windows) I restart the machine so the PATH ENV change takes effect.

Sending Tests to Selenium Server

If you’ve tested your Selenium Server hub and nodes and all looks like they are connected, you now can send a single test to the Selenium Server.  How you do that is going to be different depending on your framework.  If you use straight Python and Selenium, it will be different then with Watir-webdriver and Cucumber.

Two Goals:

  • Goal #1: Create webdriver instances that reference your Selenium Server hub.
  • Goal #2: Send your tests to Selenium Server asynchronously.

Goal #1

However you create your webdriver instances, you will need to make sure the methodology uses your Selenium Server.  I do this with a call like so:

@browser = Watir::Browser.new(:remote, :url=>"http://qa1.mydomain.com:4444/wd/hub", :desired_capabilities=> {browserName: browser_name,version: browser_version})

browser_name and _browser_version are defined on the command line.  Here’s how I do this with Cucumber.  In my Cucumber features folder, I have a sub directory called “support.”  Inside support I have a file called env.rb.  This file will be run before any tests.  So if we define various environment variables here, they will be taken at launch.

I use a couple ruby methods to allow the user to define the browser (browser_name) and version (browser_version) like so:

def browser_name
  (ENV['BROWSER'] ||= 'firefox').downcase.to_sym
end

def environment
  (ENV['ENV'] ||= 'local').downcase.to_sym
end

def browser_version
  (ENV['VER'])
end

Below that I create a Before block… like so:

Before do
  if browser_path != nil
    Selenium::WebDriver::Firefox.path= "#{browser_path}"
  end
  if environment == :grid
    @browser = Watir::Browser.new(:remote, :url=>"http://qa1.mydomain.com:4444/wd/hub", :desired_capabilities=> {browserName: browser_name,version: browser_version})
  else
  @browser = Watir::Browser.new browser_name
  end
end

From the command line, I can then call: cucumber [feature file] BROWSER=chrome ENV=grid VER=31.  That would run the specified feature file… it would pick up the ENV value of grid and that would fall into the if condition to create

@browser = Watir::Browser.new(:remote, :url=>"http://qa1.mydomain.com:4444/wd/hub", :desired_capabilities=> {browserName: browser_name,version: browser_version})

The test would then pass the desired browser of Chrome and version 31 to Selenium Server.  Selenium Server would then pick up the configuration and see if it has a node for that specific configuration.  If it does, it sends the test to that Selenium Server node.  The results would be returned to you in console.

Goal #2

If you get goal #1 working, you are now able to send your tests to a Selenium Server, which farms the test to the appropriate node.  At this point though, you are only doing one test at a time, there’s no parallel testing.   Depending on your framework, you can do this a variety of ways.  One way is to use a language that can make asynchronous method calls.  If you have a language (Grails for example) that can asynchronously iterate over your tests and send them all out at the same time to Selenium Server – that would be one way of getting all your tests running in parallel.

For me, I use Jenkins for this task.  Jenkins is useful because it can manage the jobs and que them up efficiently.  I won’t get into setting up Jenkins in this post, as I cover it in many others.  Basically you run the Jenkins war file and simply create a new Free form project that runs a batch command (which is your cucumber command)… like so:

cucumber [your feature file name] ENV=grid BROWSER=chrome VER=31

you could save the project as “[Feature being tested] – Chrome”

Then duplicate the project as “[Feature being tested] – IE” etc.

Once you have a bunch of Jenkins projects, you can run them manually by selecting each one and building it. All will be queued up to run simultaneously.

You can also use Jenkins to start all projects of a type, by choosing to run other projects together.  So you might have one Jenkins project that runs all browser tests for a single feature at the same time.

However you decide to do this, is up to you.  There are many different ways to achieve this goal.  The basic functionality you must do is send the appropriate cucumber command to run each test in your suite and that needs to be done asynchronously (so all tests are sent simultaneously to Selenium Server.)

Here’s a screenshot of my Jenkins having run a series of tests simultaneously:

Screen Shot 2015-04-06 at 2.04.12 PM

Selenium Server Setup
User Rating: 0 (0 votes)