There has been a bit of discussion in the Grails mailing list about the lack of documentation on configuring webdriver for Geb.
In this post, I will outline the steps you will need to configure the following browsers:
- Firefox
- Chrome
- Internet Explorer
- Sauce Labs / Remote Webdriver
- PhantomJS
HTMLUnit won’t be covered because it is broken for grails 2.2 and you shouldn’t be using HTMLUnit.
Adding Geb and Spock:
To start, open up your BuildConfig.groovy file.
Add the following dependency under the plugin block:
plugins{ test ":geb:0.9.0-RC-1" test(":spock:0.7") { exclude "spock-grails-support" } }
Add the following dependencies in your dependencies block:
dependencies { test "org.spockframework:spock-grails-support:0.7-groovy-2.0" test "org.seleniumhq.selenium:selenium-support:2.31.0" test "org.gebish:geb-spock:0.9.0-RC-1" }
Versions of plugins may vary so check them on maven central before adding them.
Create a blank file called GebConfig.groovy in your test/functional/ directory. We will use this file to control which driver is called.
A Sample Geb Test:
Here is a sample geb test to check that your configurations are set up correctly. Add this to your test/functional folder. This test just goes to the grails.mx.org website and checks for the title. Call it LoginSpec.groovy
import geb.spock.GebReportingSpec class LoginSpec extends GebReportingSpec { def "go to page"() { when: go "http://www.grails.org.mx" then: title == "GrailsMX | Groovy y Grails en tu idioma" } }
Also, since this file is a GebReportingSpec (i.e, takes a snapshot of your test after executing and keeps a copy of the html file), you need to set a reporting directory in the GebConfig.groovy file. Add this to the top of your GebConfig:
reportsDir = "target/geb-reports"
You’re ready to test. After setting up each Geb config, simply call grails test-app functional: to see your tests run.
Firefox:
For firefox, you simply need to include the firefox driver. In your dependencies, add:
test "org.seleniumhq.selenium:selenium-firefox-driver:2.31.0"
At this point, you don’t need to add anything to your GebConfig file since it will run the first driver it finds. But if you want to set it explicitivly, add this to GebConfig.groovy:
import org.openqa.selenium.firefox.FirefoxDriver driver = { new FirefoxDriver() }
Chrome:
For Chrome, you need to first download the chrome driver from https://code.google.com/p/chromedriver/downloads/list
After you have downloaded this file, you should save it locally. For example, /Users/tomaslin/drivers/ . Set an environment variable for webdriver.chrome.driver to this.
Alternatively, you can just do so in your GebConfig.groovy file.
Add the following to set up chromedriver:
import org.openqa.selenium.chrome.ChromeDriver driver = { System.setProperty('webdriver.chrome.driver', '/Users/tomaslin/drivers/chromedriver') new ChromeDriver() }
If you want to be able to switch drivers on the fly via configuration, follow this example – https://github.com/geb/geb-example-grails/blob/master/test/functional/GebConfig.groovy .
If you want to download the drivers automatically, follow this blog post – https://fbflex.wordpress.com/2013/01/06/geb-quickie-automatically-download-drivers-for-chrome-and-internet-explorer/
To get this to run, you need to add the chromedriver dependency in your BuildConfig.groovy file:
test "org.seleniumhq.selenium:selenium-chrome-driver:2.31.0"
Internet Explorer:
Internet explorer follows the same pattern as Chrome Driver above, except that the environment variable name is webdriver.ie.driver and it is downloaded from https://code.google.com/p/selenium/downloads/list . It is called something like IEDriverServer_x64_2.31.0.zip
Add the dependency to BuildConfig.groovy
test "org.seleniumhq.selenium:selenium-ie-driver:2.31.0"
Then add the following code to your GebConfig file:
driver = { System.setProperty("webdriver.ie.driver", new File("C:/dev/Selenium/iexploredriver.exe").getAbsolutePath()) new InternetExplorerDriver() }
Selenium Grid / Sauce Labs / Remote Web Driver:
An exciting alternative for running Geb tests is to use Cloudified web servers or local instances available via selenium grid.
In order to use this, you need to add the remote driver dependency in BuildConfig.groovy
test "org.seleniumhq.selenium:selenium-remote-driver:2.31.0"
If you are subscribed to Sauce Labs, you can simply use your credentials and demand a webdriver instance to be created on the cloud based on your requirements in your GebConfig.groovy file.
Here, I ask for a firefox instance on Windows 8.
import org.openqa.selenium.remote.DesiredCapabilities import org.openqa.selenium.remote.RemoteWebDriver driver = { DesiredCapabilities capabilities = DesiredCapabilities.firefox() capabilities.setCapability("version", "17") capabilities.setCapability("platform", "Windows 2012") new RemoteWebDriver( new URL("http://:<access_key>@ondemand.saucelabs.com:80/wd/hub"), capabilities ) }
To get a full list of sauce labs Operating systems and configurations, refer to their browsers page documentation. You can also specify a name for your test for easy identification.
My test finishes running and I see the result when I log onto the Sauce Labs website:
When I click on it, I get a detail recording of the test being ran, all the DOM elements and Events being fired, as well as a screenshot of the test:
This is pretty useful if you’re doing functional tests and continous delivery on the cloud in environments like CloudBees.
If you want to set up your own environments, for example to drive internet explorer on a virtual machine from your mac, you can use the Selenium Grid. The instructions for this are included in the link. You download a jar file to each machine, start a hub and start testing on each machine with the same instructions as above.
PhantomJS:
Finally, if you want to have a headless browsing experience that runs your tests really quickly, you can setup a Geb configuration that relies on PhantomJS. PhantomJS is a headless javascript browser based on Webkit. It is much better than HTMLUnit.
First, you need to install phantomjs via the instructions on their website. I just do this via homebrew ‘brew install phantomjs’.
After you have phantomjs installed, verify that it works by calling phantomjs in your terminal, type phantom.exit(); to exit the console.
You need to then add the ghostdriver jar to run phantomjs tests in Geb. Add the following dependency to your BuildConfig file:
test( "com.github.detro.ghostdriver:phantomjsdriver:1.0.1" ) { transitive = false }
Note: The latest version of this driver is 1.0.3, but I had difficulties getting it to work properly on my MacOS installation. 1.0.1 works fine.
The PhantomJS driver is a little trickier, but it looks like this in GebConfig.groovy
import org.openqa.selenium.phantomjs.PhantomJSDriver import org.openqa.selenium.remote.DesiredCapabilities driver = { new PhantomJSDriver(new DesiredCapabilities()) }
You can also change some of the configurations. For our projects, for example, we wanted to fix the screen size to 1028×768 so that our mobile layout does not kick in. Our config then looks as follows:
import org.openqa.selenium.phantomjs.PhantomJSDriver import org.openqa.selenium.remote.DesiredCapabilities import org.openqa.selenium.Dimension driver = { def d = new PhantomJSDriver(new DesiredCapabilities()) d.manage().window().setSize(new Dimension(1028, 768)) d }
Very I interesting! Particularly the cloud setup.
Cool stuff. Useful for the functional testing chapter of Grails in Action 🙂
One thing: in what way does HTMLUnit not work with Grails 2.2 and could you clarify why HTMLUnit shouldn’t be used anyway? I’d be interested to know the reasons.
HTMLUnit above version 2.10 fails as outlined in this post to geb-user – http://markmail.org/message/za7zxhn7kz4t5de2#query:+page:1+mid:lcuu2lcktsu5oxv7+state:results . The issue with HTMLUnit is that it sometimes will fail correct tests due to the way it some features are implemented. Solutions like PhantomJS better capture the real browser experience.
Thank you! The timing of this post is perfect for me, as I’m just starting to look at adding functional tests to my projects. Very cool stuff!
Thank you very much! It’s extremely disheartening how much churn there is with Grails — management wants to use it “because it’s Java”, but we end up fighting a great deal to get something working (IE browser testing with Geb) that “just works” in other languages (i.e., Rails & Capybara).
With the IE driver, I think people also need to be aware that the Protected Mode settings for IE need to be set to the same value for each zone. See also https://code.google.com/p/selenium/wiki/InternetExplorerDriver
Thanks for a terrific post, as always.
Thanks for this useful post. I had disabled my geb tests after upgrading to Grails 2.2 due to problematic configuration, now that I removed HTMLUnit it works fine. I didn’t need the dependency “org.seleniumhq.selenium:selenium-support:2.31.0” though, what do I need that one for?
There’s a small typo in the dependency for PhantomJS: “destro” should be “detro”.
Thanks, I have fixed the typo. Selenium support is required by Geb.
Ok, my Geb tests runs perfectly fine without selenium-support, but I see that the Geb documentation says it should be included (http://www.gebish.org/manual/current/intro.html#installation__usage)
Selenium support is needed for dropdowns ( i.e, SELECT elements )
The PhantomJS dependency pulls in selenium-java which pulls in selenium-htmlunit-driver and ultimately xerces:XerxecImpl:2.10.0 which causes problems.
These are the direct dependencies of com.github.detro.ghostdriver:phantomjsdriver:jar:1.0.1:
– org.seleniumhq.selenium:selenium-java:2.28.0
– org.seleniumhq.selenium:selenium-server:2.28.0
– org.seleniumhq.selenium:selenium-remote-driver:2.28.0
These three dependencies pulls in lots of stuff, e.g. all the selenium drivers for android, iphone, chrome etc.
It doesn’t look like any of those are needed to run my Geb tests with PhantomJS, so this works for me:
test(“com.github.detro.ghostdriver:phantomjsdriver:1.0.1”) {
transitive = false
}
Or at a minimum I need to exclude xerces:
test(“com.github.detro.ghostdriver:phantomjsdriver:1.0.1”) {
excludes ‘xercesImpl’
}
BTW: phantomjsdriver 1.0.3 works the same as 1.0.1 on my mac.
I had the problem with 1.0.3 on my mac and then upgraded from phantomjs from 1.8 to 1.9 and that fixed my problem.
You do not need to set reportsDir, it defaults to target/test-reports/geb
Pingback: Questa settimana in Grails (2013-12) - luca-canducci.com - Il blog di Luca Canducci: notizie, tips e nuove tecnologie dal mondo dell’IT.
Pingback: An Army of Solipsists » Blog Archive » This Week in Grails (2013-12)
I always get:
java.lang.NoSuchMethodError: org.apache.http.conn.scheme.Scheme.(Ljava/lang/String;ILorg/apache/http/conn/scheme/SchemeSocketFactory;)V
at org.openqa.selenium.remote.internal.HttpClientFactory.getClientConnectionManager(HttpClientFactory.java:59)
at org.openqa.selenium.remote.internal.HttpClientFactory.(HttpClientFactory.java:48)
at org.openqa.selenium.remote.HttpCommandExecutor.(HttpCommandExecutor.java:111)
at org.openqa.selenium.chrome.ChromeCommandExecutor.(ChromeCommandExecutor.java:30)
at org.openqa.selenium.chrome.ChromeDriver.(ChromeDriver.java:144)
at org.openqa.selenium.chrome.ChromeDriver.(ChromeDriver.java:86)
at geb.driver.NameBasedDriverFactory.getDriver(NameBasedDriverFactory.groovy:42)
at geb.driver.CachingDriverFactory$_getDriver_closure3.doCall(CachingDriverFactory.groovy:80)
at geb.driver.CachingDriverFactory$SimpleCache.get(CachingDriverFactory.groovy:30)
at geb.driver.CachingDriverFactory.getDriver(CachingDriverFactory.groovy:79)
at geb.Configuration.createDriver(Configuration.groovy:338)
at geb.Configuration.getDriver(Configuration.groovy:327)
at geb.Browser.getDriver(Browser.groovy:104)
at geb.report.PageSourceReporter.getPageSource(PageSourceReporter.groovy:42)
at geb.report.PageSourceReporter.writePageSource(PageSourceReporter.groovy:38)
at geb.report.PageSourceReporter.writeReport(PageSourceReporter.groovy:29)
at geb.report.CompositeReporter.writeReport(CompositeReporter.groovy:31)
at geb.Browser.report(Browser.groovy:698)
at geb.junit4.GebReportingTest.report(GebReportingTest.groovy:32)
at geb.junit4.GebReportingTest.writeGebReport(GebReportingTest.groovy:51)
My BuildConfig file is:
dependencies {
test “org.seleniumhq.selenium:selenium-chrome-driver:2.21.0”
test “org.seleniumhq.selenium:selenium-support:2.21.0”
test “org.gebish:geb-junit4:0.9.0”
}
plugins {
test “:geb:0.9.0”
}
Grails 2.0.4 – Groovy 1.8
Am I missing something?
Hi,
I am able to get the Geb Google search example working with IE/FF/Chrome/Phantomjs when using a connection with no proxy. However, when I run the same tests from the office, the proxy causes grief. FF and Chrome will prompt for username and password – which once entered allows the test to complete. IE and Phantomjs do not work when behind a proxy. Is there a way to set proxy host/port/username/password in the GebConfig file that will satisfy the office proxy? Googling hasn’t brought up anything that has worked so far.
Thanks,
Darren
Hi, nice article.
Phantomjsdriver depends on selenium-remote-driver, so by setting transitive = false you should depend on it manually:
test ‘org.seleniumhq.selenium:selenium-remote-driver:2.34.0’ // Needed by phantomjsdriver
Pingback: Groovy with Geb using Phantomjs and ssl certs | Agile, Grails, and other tech
Nice article I wrote a blog about accessing self signed certs and https using phantomjsdriver http://onekilo79.wordpress.com/2013/08/17/groovy-with-geb-using-phantomjs-and-ssl-certs/
Pingback: Keep getting JavaScript messages in Geb test | BlogoSfera
I already have Geb with maven (not Grails) and this was just the article I was looking for! I’ve just started looking at headless browser testing because I’ll soon be deploying these out to our internal Jenkins CI builds and needed to have a headless way to execute. Also, a somewhat cleaner way for the GebConfig implemenation that I have found useful is to use the environments switches. So my Geb Config looks like:
environments {
'ff' {
driver = {
def dr = new FirefoxDriver()
dr.manage().window().maximize()
return dr
}
}
'chrome' {
driver = {
new ChromeDriver(DesiredCapabilities.chrome())
}
}
'ie' {
driver = {
new InternetExplorerDriver()
}
}
'phantomjs'{
driver = {
new PhantomJSDriver(new DesiredCapabilities())
}
}
}
Then by using the geb.env vm option you can have your configurations setup up for multiple browsers.
Thank you for the useful post!
I am having problems trying to use Geb (0.9.2) and PhantomJS (1.9.7,) from a new Grails 2.3.7 app to scrape content from a web site (i.e., not from within a test). I run the following code:
def t(String url) {
def res = null
Browser.drive {
go url
res = title
}
res
}
I get an UnableToLoadAnyDriversException listing htmlunit, Ffox, IE and Chrome drivers, but not PhantomJS. My dependencies are as follows:
compile (“com.github.detro.ghostdriver:phantomjsdriver:1.1.0”) {
transitive = false
}
compile “org.seleniumhq.selenium:selenium-remote-driver:2.40.0”
compile “org.seleniumhq.selenium:selenium-support:2.40.0”
Any idea of what I’m doing wrong?
BTW, I should add that I am able to use the Firefox driver.
I wrote a short tutorial on how to configure Chrome and Geb on Grails: http://keyboarddays.blogspot.it/2014/04/how-to-configure-grails-and-geb-as.html
@Giorgio: my question was about PhantomJS, not Chrome.