chapter 6
DESCRIPTION
testingTRANSCRIPT
Selenium Tutorial : Selenium Remote Control
7. Selenium Remote Control (RC)
7.1. Overview
While Selenium IDE may seem a productive and efficient tool for writing test-cases, it lacks many essential features of a testing tool:
o Conditional statements
o Loops
o Logging
o Exception handling
o Reporting
o Test fixtures and data-driven tests
o Test dependencies
o Taking screenshots
Selenium RC is the answer to a more powerful test-suite for your applications.
It follows a client/server model allowing client libraries to execute tests on a browser controlled by the server.
Figure 7. Overview of Selenium RC
7.2. Selenium Server
Selenium server is the program that drives the browser It embeds Selenium Core framework and injects it into the browser
It communicates with the running test client and drives the browser
Client tests sends commands that the server interpretes in order to drive the browser
The server sends back results to the client
Client and server communicates via HTTP GETs and POSTs so you can easily plug into
Server is configurable at startup via command-line options. use java -jar selenium-server.jar -h to see the list of options
7.3. Client libraries
Client libraries provides the API to program tests and execute them on the server Each implementation provides access to all Selenium commands
Supported API implementation exists in:
o Java (also accessible via Groovy)
o .Net
o PHP
o Python
o Perl
o Ruby
7.4. Lab 3 : Installation of Selenium RC
7.4.1. Prerequisites A JVM installed on the system A Ruby distribution with the rspec and selenium-client gems installed if
you’re working
The Selenium RC archive
7.4.2. Download The Tested Application
In the folder of your choice, execute the following command:
git clone http://github.com/wolframarnold/selenium-test-app.git
Go to the selenium-test-app folder and run the following: o cp
./vendor/plugins/active_scaffold/test/mock_app/config/database.yml
./config/
o rake db:migrate
Now you should be able to lauch the application with the script server available in the scripts folder:
./scripts/server
The application should be available at http://localhost:3000
7.4.3. Running The RC Server Unzip the Selenium RC archive somewhere on your system Go into the selenium-rc, then the selenium-server folder
Open a terminal in this folder and enter the command java -jar selenium-server.jar
If there’s no error messages, your Selenium RC server should be running now.
7.4.4. Running A Test (Java) Create a new Java project in Eclipse or your Java IDE Add the selenium-java-client-driver.jar jar to the project’s classpath
Add a new JUnit test-case to the project. When asked, select Junit 4
You should now have an empty .java file
Open the lab2 test-case on Selenium IDE
On Selenium IDE, open the Options menu then Format… and click Java (Junit)
Copy/paste the contents in the JUnit file on Eclipse
Change the package name at your will
You may have to fix the imports
o Click on the following icon and choose the most appropriate option to correct the file
o You may also press Ctrl + Shift + O to let Eclipse do it automatically
At this point you shouldn’t have any more errors and you are ready to run the test
Selenium RC will open a couple of Firefox windows and run the test
7.4.5. Running A Test (Ruby) Open the lab2 test-case on Selenium IDE and export it as Ruby (rspec) A little workaround is needed, open the exported file:
o On line 47, where you should have: /^Are you sure you want to delete <suggestion_name>[\s\S]$/ =~ page.get_confirmation.should be_true
o Change it to: page.get_confirmation.should match(/^Are you sure you want to delete <suggestion_name>[\s\S]$/)
Run the test with spec <filename>.rb
Selenium RC should launch a couple of new browser windows and run the test
7.5. Junit
Junit is the reference unit-testing framework for Java The framework allows you to test your applications using specific classes containing the logic
performing actions on the tested classes and checking the results
Eclipse provides support for Junit, so we’ll be using that
JUnit 3 uses named methods to detect set-up and test methods
JUnit 3 cheat sheet:
import static org.junit.Assert.assertEquals; public class AdditionTest { // DeepThought dt; public void setUp() { // dt = new DeepThought(); dt.initialize(); } public void tearDown() { // dt.closeQASession(); saveResult(); } public void testDeepThought() { // int answer = dt.ask("What is the meaning of life, the universe and
everything?"); assertEquals(42, answer); // }
}
The tests are embedded within a classic JavaBean
The setUp() method will be executed once, before any other method
tearDown() method is executed after the last test method
Name your tests methods following the testSomething() pattern. They will be executed in the order of declaration
Junit uses assert... methods to provide verification of values.
Note
In our tests, we’ll use verify... methods provided by the selenium driver instead
7.6. RSpec
RSpec is a Behaviour Driven Development framework for Ruby It provides a framework that tests your apps according to defined behaviors
In Behavior Driven Development (BDD), you first define the behaviors of your app according to the client’s need, then your write the tests that validate these behaviors and then you start to develop your application.
It is Agile-oriented
Behaviors are defined in a spec file containing set-up methods as well as methods providing tests for a given behavior
You run tests with the spec command in a terminal
RSpec cheat sheet:
require 'thing' describe Thing do before do @thing = Thing.new end it "should find the Answer to the Ultimate Question of Life, the
Universe, and Everything" do @thing.answer.should == 42 end it "should enforce the Answer to the Ultimate Question of Life, the
Universe, and Everything" do @thing.answer = 24 @thing.enforce @thing.answer.should be 42 end
end
Load the tested file (you don’t need to specify the .rb extension)
describe MyClass do
describe declares what is being testedYou can specify code to be run before (before) and after (after). You can execute code before each example with before(:all)
Each example begins with it followed by a string describing the behavior to be tested
object.should and object.should_not are used to compare actual and expected values
examples:
o o.should == <value> and o.should be <value> are equivalent o o.should be_close <value>, <tolerance> tests if a value is within
a certain range
o o.should match <regexp> tests if the value matches a regular
expression
o o.should raise_error tests if a method raises an error (you can specify the type of error as arguments)
o o.should have (5).things tests if a collection contains 5 items exactly. have_at_least and have_at_most are also available
7.7. JavaScript
Since Selenium is based on JavaScript, you can use it in your tests It is an excellent way to extract information from the pages for later reuse
There are 2 methods available:
o getEval(script): it takes the script as a string, executes it and return the value to which the script evaluates too. In ruby use get_eval or js_eval
Using this method, the window object refers to the Selenium context, which is different from the tested application’s JavaScript context
To work around this, you need to get the application’s window object using currentwindow = this.browserbot.getCurrentWindow() * If you want to get an element, just use element = this.browserbot.findElement("locator")
o runScript(script): it actually adds a <script> tag in the current page of the tested application, making it easier to debug
7.8. Fixtures
Usually, fixtures designate the environment setup for the test-cases It is a very abstract notion and in practice it could be very different from a project to another
depending on the project’s features
In practice, fixtures are a set of tools allowing the test of an application under a pre-determined environment that produces previsible results
The main motivation is to avoid errors due to changing environments and the side-effects that may occur
In our case, Selenium doesn’t provide any support for fixtures so you have to do it by hand using your test framework’s fixtures capabilities
RSpec and JUnit have support for fixtures through the set-up methods
7.9. Lab 4 : Improving a test
7.9.1. Current Situation Test is brittle : change in the structure of the table displaying suggestions breaks the test Locators are complex
We can’t do Fixtures
7.9.2. How are we going to change that? You will first creates a suggestion Then you will find a way to delete that suggestion using only the id of the delete link
Tip
Observe the id of each table row and the corresponding delete link. You should be able to extract the numeric part of the id and use it to target the delete button. Use the following snippet to get the id: Java:
String script = "var suggestion_ids = new Array();" + "page =
selenium.browserbot.getCurrentWindow().document;" + "table = page.getElementById('as_suggestions-
content').childNodes[1];" + "var id = table.rows[2].id;" + "if(id && id != undefined) {" + " suggestion_ids.push(id.match(/[0-9]+/g));" + "}" + "suggestion_ids;";
selenium.getEval(script);
Ruby: script = "var suggestion_ids = new Array();" + "page = selenium.browserbot.getCurrentWindow().document;" + "table = page.getElementById('as_suggestions-
content').childNodes[1];" + "var id = table.rows[2].id;" + "if (id && id != undefined) {" + "suggestion_ids.push(id.match(/[0-9]+/g));" + "}" + "suggestion_ids;"
suggestion_id = page.js_eval(script) Bonus: Make a loop that creates more suggestions and find a way to iterate over the table to
delete them using javascript