The goal of this vignette is to give a basic overview of how one might approach using RSelenium with combinations of operating systems (OS) and browsers both locally and remotely.
The default browser for RSelenium
is firefox. When a
remoteDriver
class is instantiated using default options
for example remdr <- remoteDriver()
then the browser
listed is firefox.
## $remoteServerAddr
## [1] "localhost"
##
## $port
## [1] 4444
##
## $browserName
## [1] "firefox"
##
## $version
## [1] ""
##
## $platform
## [1] "ANY"
##
## $javascript
## [1] TRUE
##
## $autoClose
## [1] FALSE
##
## $nativeEvents
## [1] TRUE
##
## $extraCapabilities
## list()
Other browsers can be driven using RSelenium
. We shall
split these browsers into three groups. Full-fledged browsers, headless
browsers and mobile browsers.
The standalone selenium jar has the ability to drive other
full-fledged browsers such as chrome, internet explorer, safari and
opera. First we shall look at how to drive chrome using
RSelenium
Firstly we note that chrome in this instance can be considered as having three parts. There is the browser itself (“chrome”), the language bindings provided by the Selenium project (“the driver”) and an executable downloaded from the Chromium project which acts as a bridge between “chrome” and the “driver”. This executable is called “chromedriver”. We need to have a “chromedriver” running. First we need to locate one. The download directory for chromedriver is currently located at http://chromedriver.storage.googleapis.com/index.html. In this example we shall look at running chrome on a windows platform so we will download the windows chromedriver. The most uptodate version of chromedriver at the time of writing was 2.9. In the notes this supports chrome v31-34. We are running chrome 33 so this is fine.
----------ChromeDriver v2.9 (2014-01-31)----------
Supports Chrome v31-34
We download the appropriate file
for windows and extract the .exe to our Documents folder. The .exe can
be placed where the user pleases but it must be in the system path. In
this case we placed in the Documents folder namely
C:\Users\john\Documents
. This directory was added to the
system path.
We assume that a selenium server is also running. A chrome browser can be controlled as follows:
require(RSelenium)
remDr <- remoteDriver(browserName = "chrome")
remDr$open()
head(remDr$sessionInfo)
## $platform
## [1] "WIN8"
##
## $acceptSslCerts
## [1] TRUE
##
## $javascriptEnabled
## [1] TRUE
##
## $browserName
## [1] "chrome"
##
## $chrome
## $chrome$userDataDir
## [1] "C:\\Users\\john\\AppData\\Local\\Temp\\scoped_dir24584_12002"
##
##
## $rotatable
## [1] FALSE
NOTE: Internet Explorer 11 has retired as of June 15, 2022.
Similarly to the chrome browser you do not need to run an installer before using the InternetExplorerDriver, though some configuration is required. The standalone server executable must be downloaded from the Downloads page and placed in your PATH. Again we need to download this executable and place it in our path. At the time of writing the internet explorer .exe is included with the main standalone server here. The current release is 2.40. The system I am running is 64 bit so we download the 64bit version. For simplicity we again place this in our Documents directory namely C:. This directory is already in the system path from running the chrome example. If you want to place the internet explorer .exe in another folder add this folder to your system path. To control internet explorer as a browser is now as simple as:
require(RSelenium)
remDr <- remoteDriver(browserName = "internet explorer")
remDr$open()
head(remDr$sessionInfo, 7)
## $platform
## [1] "WINDOWS"
##
## $javascriptEnabled
## [1] TRUE
##
## $elementScrollBehavior
## [1] 0
##
## $ignoreZoomSetting
## [1] FALSE
##
## $enablePersistentHover
## [1] TRUE
##
## $ie.ensureCleanSession
## [1] FALSE
##
## $browserName
## [1] "internet explorer"
Currently Apple have discontinued developement of safari for windows. The latest version for windows was 5.1.7 available here. Starting with Selenium 2.30.0, the SafariDriver comes bundled with the Selenium server so nothing other then having safari installed should be required. For the purposes of this vignette I downloaded and installed safari 5.1.7 on a windows 8.1 system.
Once installed controlling safari was as easy as:
require(RSelenium)
remDr <- remoteDriver(browserName = "safari")
remDr$open()
head(remDr$sessionInfo)
## $platform
## [1] "WINDOWS"
##
## $cssSelectorsEnabled
## [1] TRUE
##
## $javascriptEnabled
## [1] TRUE
##
## $secureSsl
## [1] TRUE
##
## $browserName
## [1] "safari"
##
## $webdriver.remote.sessionid
## [1] "a18da818-5160-47c4-8e88-7e95605c5cab"
Opera is currently not supported for versions newer then 12.
Next we shall look at running what is known as headless browsers. Usually a browser can do three things
A headless browser handles items 1 and 2 but doesn’t carryout 3. This means it doesn’t display anything. All pages etc. are in memory rather then displayed to the user. The result of this is that headless browsers should perform faster then their full-fledged competitors which could be welcome news to speed up testing.
NOTE: PhantomJS development is suspended until further notice.
The first headless browser we shall look at is
phantomjs
. Firstly download the relevant zip file for your
OS from here. We are
using windows so we downloaded phantomjs-2.1.1-windows.zip.
It is sufficient to place the location of the directory containing
phantomjs.exe
in your path. In this case we probably could
have just extracted phantomjs.exe
to the Documents folder
where chromedriver etc current reside.
However I extracted it to the desktop keeping the contents of the
zip. The reasoning behind this was that phantomjs is driven by selenium
using ghostdriver. At
some point the version of ghostdriver phantomjs uses will be upgraded
and will accept calls from an unexposed method
phantomExecute
of the RSelenium remoteDriver
class. There are interesting scripts contained in the phantomjs /example
directory like netsniff.js which captures network traffic in HAR format.
When the phantomExecute
method is exposed these scripts
will be useful. So I added the location of the .exe to my path namely
the directory
C:\Users\john\Desktop\phantomjs-1.9.7-windows
. Once your
operating system can find phantomjs.exe
or the equivalent
driving a phantomjs browser is as easy as:
require(RSelenium)
remDr <- remoteDriver(browserName = "phantomjs")
remDr$open()
head(remDr$sessionInfo)
## $platform
## [1] "XP"
##
## $acceptSslCerts
## [1] FALSE
##
## $javascriptEnabled
## [1] TRUE
##
## $browserName
## [1] "phantomjs"
##
## $rotatable
## [1] FALSE
##
## $driverVersion
## [1] "1.1.0"
We can take a screenshot even thou the browser is headless:
PhantomJS is excellent. It has only recently as of version 1.8 had Ghost Driver integration and hopefully its importance will increase further.
The original headless browser for selenium was
htmlunit
.
Setting up multiple OS/browsers combinations locally is not always the best use of ones time. It is an interesting exercise to implement for example an Android platform locally but the overhead of having multiple systems and browsers quickly overcomes the utility. There are professional service providers who maintain a suite of OS/browsers that can be utilised for testing. Companies such as Sauce Labs and Browser Stack offer free automated testing to open source projects. In this vignette we will demonstrate remote testing using Sauce Labs.
We assume in this vignette that you are setting up Sauce Labs for an
open source project. Firstly you should register your project here. On the account page you will
find the access key for your account that is in a similar format to
49953c74-5c46-4ff9-b584-cf31a4c71809
. Using Sauce Labs is
pretty straightforward. You need to tell it what OS/Browser combination
you would like. A list of possible setups can be viewed here.
As an example lets suppose we wished to run google chrome version 33 on
OSX version mavericks.
require(RSelenium)
user <- "rselenium0" # Your Sauce Labs username
pass <- "49953c74-5c46-4ff9-b584-cf31a4c71809" # Your Sauce Labs access key
port <- 80
ip <- paste0(user, ':', pass, "@ondemand.saucelabs.com")
rdBrowser <- "chrome"
version <- "33"
platform <- "OS X 10.9"
extraCapabilities <- list(
name = "RSelenium OS/Browsers vignette first example",
username = user,
accessKey = pass,
tags = list("RSelenium-vignette", "OS/Browsers-vignette")
)
remDr <- remoteDriver$new(
remoteServerAddr = ip,
port = port,
browserName = rdBrowser,
version = version,
platform = platform,
extraCapabilities = extraCapabilities
)
We state the browser and OS we require (chrome 33/ Mac OSX 10.9). The
user and password are used to form an appropriate ip address for our
remote server (http://rselenium0:[email protected]
in this case). They are also passed as extraCapabilities
to
the remote Selenium server.
We give our test a name
and any additional
tags
we wish that are passed to the remote Selenium server.
Details of the name and tags are given here.
They are used to annotate our tests.
As a basic first example we will run a script using the mavericks/ chrome 33 combination. We run the following commands:
testScript <- function(remDr) {
remDr$open()
remDr$navigate("http://www.google.com/ncr")
Sys.sleep(2)
# highlight the query box
remDr$findElement("name", "q")$highlightElement()
Sys.sleep(2)
# goto rproject
remDr$navigate("http://www.r-project.org")
# go Back
remDr$goBack()
# go Forward
remDr$goForward()
Sys.sleep(2)
webElems <- remDr$findElements("css selector", "frame")
# highlight the frames
lapply(webElems, function(x){x$highlightElement()})
remDr$close()
}
testScript(remDr)
And that’s it. We have ran our first remote test using Sauce Labs. The results of the test can be viewed here. I think you will agree its a nice setup. We have access to screenshots of all the commands we issued and a video (screencast) of the test run. We can view the selenium server logs and the medadata associated with our test.
We can easily extend the simple test we ran for multiple OS/Browser combinations. The browser and platform variables need to be assigned the combinations we require.
osBrowser <- list(
"OS X 10.9" = list(
browser = list("safari", "firefox"),
version = list('7', '28')
),
"Windows 8" = list(
browser = list("chrome", "firefox", "internet explorer"),
version = list('33', '28', '10')
),
"Linux" = list(
browser = list("chrome", "firefox", "opera"),
version = list('33', '28', '12')
)
)
lapply(seq_along(osBrowser), function(x) {
platform <- names(osBrowser)[x]
lapply(seq_along(osBrowser[[x]]$browser), function(y){
rdBrowser <- osBrowser[[x]]$browser[[y]]
version <- osBrowser[[x]]$version[[y]]
remDr <- remoteDriver$new(
remoteServerAddr = ip,
port = port,
browserName = rdBrowser,
version = version,
platform = platform,
extraCapabilities = extraCapabilities
)
testScript(remDr)
})
})
To view the results you can go to the RSelenium
project
page on Sauce Labs.
Listed here are all the tests ran on the RSelenium
package.
A partial search by name Browsers vignette first example
will give the results of this test. There are a few repeats of the first
Mavericks/ chrome 33 test where I tuned the script.
Testing external webpages and websites across a range of operating
systems and browsers can be achieved using Sauce Labs as we observed in
the last section. Often however especially in a development phase of a
project we either do not have or do not want an external version of our
webpage/website/webapp. A good example would be our
shinytestapp
. Lets open a new R session and run our
testapp.
To access our app we would require the ip address
http://localhost:3000/
. How do we access this from a remote
webdriver?
Thankfully Sauce Labs have a solution for this known as Sauce Connect. Sauce Connect is a secure tunneling app which allows you to execute tests securely when testing behind firewalls via a secure connection between Sauce Labs client cloud and your environment. This allows you to drive an external Browser and have it interact with a local webpage/website/webapp.
Firstly you need to download the Sauce Connect zip for the operating
system you are using to run your tests on. This machine I will be
testing from is running windows 8.1 so I download the windows
zip. I unzipped Sauce Connect to the Documents folder so it is now
accessible at C:\Users\john\Documents\sc-4.1-win32
. From a
windows command prompt we navigate to the Sauce Connect bin directory
and run the .exe file supplying our Sauce Labs user name and access
key.
sc.exe -u rselenium0 -k 49953c74-5c46-4
ff9-b584-cf31a4c71809
We opened our shinytestapp on port 3000 because Sauce Connect only
supports a set number of ports. All ports can be used but for this you
need a locally-defined domain name (which can be set in your hosts file)
rather than localhost. This is simple to do but for the purposes of this
vignette we shall connect to http://localhost:3000
. Again
to start with we shall use Mavericks with Chrome 33.
require(RSelenium)
user <- "rselenium0" # Your Sauce Labs username
pass <- "49953c74-5c46-4ff9-b584-cf31a4c71809" # Your Sauce Labs access key
port <- 80
ip <- paste0(user, ‘:’, pass,
“@ondemand.saucelabs.com”)
port <- 4445
ip <- paste0(user, ':', pass, "@localhost")
rdBrowser <- "firefox"
version <- "26"
platform <- "Linux"
extraCapabilities <- list(
name = "RSelenium OS/Browsers vignette second example",
username = user,
accessKey = pass,
tags = list(
"RSelenium-vignette",
"OS/Browsers-vignette",
"Example 2"
)
)
remDr <- remoteDriver$new(
remoteServerAddr = ip,
port = port,
browserName = rdBrowser,
version = version,
platform = platform,
extraCapabilities = extraCapabilities
)
Everything is as before the exception is that when we ask to browse
to a localhost address Sauce Connect will intervene. Also we connect to
Sauce Labs through Sauce Connect on localhost:4445
by
default instead of ondemand.saucelabs.com:80
.
localScript <- function(remDr){
remDr$open()
remDr$setImplicitWaitTimeout(2000) # wait for elements for 2 seconds
remDr$navigate("http://localhost:3000")
Sys.sleep(2)
# highlight the labels
webElems <- remDr$findElements("css selector", "#ctrlSelect span")
lapply(webElems, function(x) {x$highlightElement()})
Sys.sleep(2)
appIds <- c("summary", "distPlot", "ggPlot", "dttable")
# Click each checkbox and check for its output
lapply(seq_along(webElems), function(x) {
if(!webElems[[x]]$isElementSelected()[[1]]) {
webElems[[x]]$clickElement()
# test for its output
out <- remDr$findElement("id", appIds[x])
out$highlightElement()
}
})
remDr$close()
}
localScript(remDr)