Monday, November 24, 2014

A Selenium Hub and WebDriver Introduction on Mac OS X

Selenium is open source software used for automating browser behavior. It's commonly used for automated functional testing. There are three major components to Selenium grid- the IDE which is used for recording actions and creating the actual tests, the hub which is responsible for coordinating the various nodes when you're running your tests, and you have the node itself which is the program that runs the browser.

Prerequisites: This guide was written for Mac OS X users.

Setup

Installation

  1. Navigate to Oracle's Java SE Downloads page and download the latest version of the JDK and run the DMG.
  2. Navigate to http://docs.seleniumhq.org/download/ and download the latest version of Selenium Server to your ~/Downloads folder. Replace any instances of x.x.x below with your version number.

Starting the Hub

# Create a selenium folder in your home directory
mkdir ~/selenium

mv ~/Downloads/selenium-server-standalone-x.x.x.jar ~/selenium
cd ~/selenium

# start the hub
java -jar selenium-server-standalone-x.x.x.jar -role hub

# hub output
# 00:37:16.885 INFO - Launching a selenium grid server

# verify that the hub is running
curl -iv localhost:4444

The hub will run on port 4444 by default. You'll also be able to verify the hub is running by navigating to localhost:4444 in your browser. Now either send the process to the background or open up a new terminal window.

Attaching a Node

cd ~/selenium

# start the node and specify hub (one line)
java -jar selenium-server-standalone-x.x.x.jar -role webdriver http://localhost:4444/grid/register
-maxSession 20 -port 5555

# node output
# 00:52:39.115 INFO - Launching a selenium grid node

As you can see in the above example, you have to specificy the location of the hub. So you can have a hub running locally, under an IP or FQDN and your node will be able to reach it. You'll also notice that we've specified 20 max sessions over the default 5. This indicates the number of browsers that can be open on this node at any given time. Finally, we designate port 5555 for our node. You can repeat this process for every machine you need to connect to the hub. Keep in mind that the hub won't run the test against the nodes, concurrently. It'll choose the first node and only run the test on that machine. We'll be diving into concurrency in a follow up article.

Selenium IDE

Creating the Test Case

  1. Return to http://docs.seleniumhq.org/download/ and download Selenium IDE, a Firefox plugin. Make sure to download the plugin using Firefox.
  2. In Firefox's toolbar, select "Tools" and then "Selenium IDE".
  3. Click the record button and begin performing some actions in your browser.

For this example, we've recorded a basic google search of the term "Selenium".


Exporting the Test Case

  1. Right click the test case in the sidebar, click "Properties" and change the name to "google_test_case".
  2. Click "File" >> "Save Test Case As..." and save it into the selenium folder you created earlier.
  3. Click "File" >> "Export Test Case As..." >> "Python 2 / unittest / WebDriver" to make it compatible with Selenium Grid.
  4. Name the file "google_test_case.py"

Running Our Test Case

Open ~/selenium/google_test_case.py.

Warning: To run against the hub, you have to comment out self.driver = webdriver.Firefox() and replace it with a Remote instance that points to the hub. See example below.

# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoAlertPresentException
import unittest, time, re

class GoogleTestCase(unittest.TestCase):
    def setUp(self):
        #self.driver = webdriver.Firefox()
        self.driver = webdriver.Remote("http://localhost:4444/wd/hub", webdriver.DesiredCapabili
ties.FIREFOX.copy())

        self.driver.implicitly_wait(30)
        self.base_url = "https://www.google.com/"
        self.verificationErrors = []
        self.accept_next_alert = True
    
    def test_google_test_case(self):
        driver = self.driver
        driver.get(self.base_url + "/")
        driver.find_element_by_id("gbqfq").clear()
        driver.find_element_by_id("gbqfq").send_keys("Selenium")
    
    def is_element_present(self, how, what):
        try: self.driver.find_element(by=how, value=what)
        except NoSuchElementException, e: return False
        return True
    
    def is_alert_present(self):
        try: self.driver.switch_to_alert()
        except NoAlertPresentException, e: return False
        return True
    
    def close_alert_and_get_its_text(self):
        try:
            alert = self.driver.switch_to_alert()
            alert_text = alert.text
            if self.accept_next_alert:
                alert.accept()
            else:
                alert.dismiss()
            return alert_text
        finally: self.accept_next_alert = True
    
    def tearDown(self):
        self.driver.quit()
        self.assertEqual([], self.verificationErrors)

if __name__ == "__main__":
    unittest.main()

Now we're ready to run our test case.

# if you haven't installed Python yet...
brew install python 

# install the client libraries for Selenium for Python
sudo pip install -U selenium

# run the script against grid
python ~/selenium/google_test_case.py

# script output
.
----------------------------------------------
Ran 1 test in 4.629s

OK

# hub output
03:39:28.843 INFO - Got a request to create a new session: Capabilities [{browserName=firefox...
03:39:28.843 INFO - Available nodes: [host :http://192.168.1.104:5555]
03:39:28.843 INFO - Trying to create a new session on node host :http://192.168.1.104:5555
03:39:28.843 INFO - Trying to create a new session on test slot {seleniumProtocol=WebDriver...

# node output
03:39:28.846 INFO - Executing: [new session: Capabilities [{browserName=firefox, javascript...
03:39:28.847 INFO - Creating a new session for Capabilities [{browserName=firefox, javascript...
03:39:31.183 INFO - Done: [new session: Capabilities [{browserName=firefox, javascriptEnabled...
03:39:31.201 INFO - Executing: [implicitly wait: 30000])
03:39:31.223 INFO - Done: [implicitly wait: 30000]
03:39:31.234 INFO - Executing: [get: https://www.google.com//])
03:39:32.357 INFO - Done: [get: https://www.google.com//]
03:39:32.367 INFO - Executing: [find element: By.id: gbqfq])
03:39:32.515 INFO - Done: [find element: By.id: gbqfq]
03:39:32.522 INFO - Executing: [clear: 0 [[FirefoxDriver: firefox on MAC (96e26c0f-9bbb-3344...
03:39:32.540 INFO - Done: [clear: 0 [[FirefoxDriver: firefox on MAC (96e26c0f-9bbb-3344-8e62...
03:39:32.546 INFO - Executing: [find element: By.id: gbqfq])
03:39:32.554 INFO - Done: [find element: By.id: gbqfq]
03:39:32.560 INFO - Executing: [send keys: 0 [[FirefoxDriver: firefox on MAC (96e26c0f-9bbb...
03:39:32.643 INFO - Done: [send keys: 0 [[FirefoxDriver: firefox on MAC (96e26c0f-9bbb-3344...
03:39:32.650 INFO - Executing: [delete session: d6febfe7-8d37-4f29-ba62-2d7e99cb3d5b])
03:39:32.733 INFO - Done: [delete session: d6febfe7-8d37-4f29-ba62-2d7e99cb3d5b]

That concludes this introductory tutorial. In future articles, we'll be exploring multiple browsers, devices, and diving into Selenium's advanced features. Until next time.

No comments:

Post a Comment