Geb drive method - groovy

I'm trying to learn how to use Geb and I'm getting an error. Could you guys help me out?
I'm trying to use the drive method but it is not working. I've tested a few of the other Browser's methods and they work all right. Just the drive method is giving me trouble.
I've checked the API and googled around but didn't find anything helpful. The strange thing is the fact that I don't get an error message. There is no Exception. I'm running the code on Groovy's console and Firefox just chills for a while and then the execution finishes.
Geb 0.9.2, FirefoxDriver and JDK 7
import org.openqa.selenium.WebDriver;
import geb.Browser
import org.openqa.selenium.firefox.FirefoxDriver
public class MyTest {
Browser browser;
void test(){
browser = new Browser(driver: new FirefoxDriver())
browser.go "http://www.google.com" // this works
browser.$("div button", name: "btnK").text() == "Google Search" // this works
browser.drive { // WHY U NO WORK?!!
go "http://www.google.com"
}
}
}
x = MyTest()
x.test()

You should know that drive() is a static method and it's designed to be used in scripts where you don't instantiate a browser instance. You have to decide - you either use a browser instance or the Browser.drive {} method. Yo cannot do both.
You might also consider using one of the integrations with testing frameworks - by doing so you'll get Geb to manage a browser instance for you.

Related

Quit driver after each Geb Spock test

I am running Geb/Spock tests in Sauce Connect, and I would prefer to have unique instances of the RemoteWebDriver per test. This way, the Sauce reports would be divided by test, which makes it easy to diagnose failures. I'm not concerned (right now) about the additional performance overhead, because as it stands running all our Geb tests via one RemoteWebDriver instance is not helpful at all - it takes a very long time to coordinate the results with the Sauce screenshots/screencasts, and when timeouts occur (which is a high possibility in a long running job over Sauce Connect) there is usually some test failure spillover.
I tried this in a class that extends GebReportingSpec:
def cleanup() {
if (System.getProperty('geb.env')?.contains('sauce')) {
setSauceJobStatus()
driver.quit()
}
}
And of course, I create a new RemoteWebDriver in the setup() method.
With this approach I get a unique Sauce Connect session per test, and the results are all beautifully organized in Sauce. HOWEVER, all the tests fail due to:
"org.openqa.selenium.remote.SessionNotFoundException: Session ID is null. Using WebDriver after calling quit()?"
It turns out that the cleanup() method in GebReportingSpec calls out to this method:
void report(String label = "") {
browser.report(ReporterSupport.toTestReportLabel(_gebReportingSpecTestCounter, _gebReportingPerTestCounter++, _gebReportingSpecTestName.methodName, label))
}
Which throws this stack trace:
at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:125)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:572)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:622)
at org.openqa.selenium.remote.RemoteWebDriver.getPageSource(RemoteWebDriver.java:459)
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:788)
at geb.spock.GebReportingSpec.report(GebReportingSpec.groovy:44)
at geb.spock.GebReportingSpec.cleanup(GebReportingSpec.groovy:39)
It's assuming that the WebDriver instance is still around when the GebReportingSpec cleanup() method is called, so that the reporting information can be prepared.
So, my approach is obviously not the "Geb way".... I'm wondering if anyone can clue me in on how to properly create a unique driver per Spock test?
Unfortunately you've hit a limitation of GebReportingSpec implementation and the fixed order of execution of Spock's setup and cleanup methods in inheritance hierarchy. What you should do is to quit your browser in a method that overrides GebSpec.resetBrowser() instead of cleanup():
void resetBrowser() {
def driver = browser.driver
super.resetBrowser()
if (System.getProperty('geb.env')?.contains('sauce')) {
driver.quit()
}
}
Getting a local reference to the driver and then calling super method is important because calling the super method will clear browser reference which means that you won't be able to get hold of the driver after that.
Also, you should not create a new RemoteWebDriver in setup() but you should disable driver caching which means that a new driver will be created per driver request (a driver is requested per browser creation and a new browser is created per each test) instead of the cached one being reused.
If you use browser.quit(), then you will get an exception and the test will be failed. You can try the following snippet at the very beginning of your class, it should work just fine:
def setup() {
browser.config.cacheDriver = false
browser.driver = browser.config.driver
}
def cleanup() {
browser.close()
}
Cheers!

Check the url in a Geb/Spock test

In my Spock functional test, I want to test that the current location of the browser is not a certain url. I know I can do:
try {
at(PageWithUrlIDontWant)
// do something
} catch (AssertionError) {
// pass because this is the common branch
}
However, this is using exceptions to control branching. Is there a way, besides at, to check what url the browser is at? I have tried page.pageUrl and browser.pageUrl but they are both null.
As of Geb 0.7.0, there is a new isAt() method on the class Browser. GebSpec proxies methodMissing calls to it's Browser instance so this method is available in your test. This method returns true/false instead of throwing an exception and should be exposed.
Example:
def "navigating to GoodPage doesn't up at BadPage"() {
when:
to GoodPage
then:
!isAt(BadPage)
}

How do I keep the browser open after a coded ui test finishes?

I'm using Visual Studio 2012 Coded UI tests for a web application. I have a test for logging into the app which starts the browser, locates the login dialogue, enters credentials, and then clicks ok. I have an assertion which checks for the correct url after the login. This test appears to function correctly. My problem is that it closes the browser after the test runs. I need to keep the browser open, so I can run the next test in my sequence. How do I do this?
At the moment, I don't have anything in my [TestCleanup()] section. I'm assuming that what I'm looking for goes here, but so far I haven't had a lot of luck figuring out what that is supposed to be.
I don't have the original source where I found this solution :(
You can have a method like the one showed below. This method needs to be called in TestSetup. Also declare a class level variable _browserWindow of the tyep BrowserWindow
private void SetBrowser()
{
if(_browserWindow == null)
{
BrowserWindow.CurrentBrowser = "ie";
_browserWindow = BrowserWindow.Launch("http://www.google.com");
_browserWindow.CloseOnPlaybackCleanup = false;
_browserWindow.Maximized = !_browserWindow.Maximized;
}
else
{
BrowserWindow.CurrentBrowser = "ie";
_browserWindow = BrowserWindow.Locate("Google");
_browserWindow.Maximized = !_browserWindow.Maximized;
}
}
Ok, so what I needed to have happen was the launch and login before each test. I thought what I wanted was to run the browser and login test first, and then each additional test. After reading more, I've decided what I actually wanted was to run this logic as initialization code for each test. I've done that by adding this code to the default [TestInitialize()] generated when I started the coded ui project in Visual Studio 2012.
I have found the following method to work for my data driven coded UI test in Visual Studio 2015.
You will want to use [ClassInitialize] and get your browser open and direct it according to where your [TestMethod] begins.
Use [ClassCleanup] to release the resources after all the methods in the test class have been executed.
You can redirect test methods different after the class has been initialized by using the [TestInitialize] and clean-up test using the [TestCleanup]. Be careful with those though because they will occur for each test method and if it closes your browser instance your following test will fail.
private static BrowserWindow browserWindow = null;
[ClassInitialize]
public static void ClassInitialize(TestContext context)
{
Playback.Initialize();
browserWindow = BrowserWindow.Launch(new Uri("http://198.238.204.79/"));
}
[ClassCleanup]
public static void TestCleanup()
{
browserWindow.Close();
Playback.Cleanup();
}

Waitforpagetoload error?

In my selenium webdriver code I'm trying to get my page to wait for it to load before it starts finding elements and driving them(entering text into username and password)
I tried using driver.waitforpagetoload(); but it returned this error
Error 1 'OpenQA.Selenium.IWebDriver' does not contain a definition for 'waitforpagetoload' and no extension method 'waitforpagetoload' accepting a first argument of type 'OpenQA.Selenium.IWebDriver' could be found (are you missing a using directive or an assembly reference?)
What type of reference to I need to add?
(coding in c#)
I found it was helpful to use Thread.Sleep(# of milliseconds), which allowed the pages to load before continuing onto the next element.
Example:
using System;
namespace SeleniumTests
{
[TestFixture]
public class FireFoxTests
{
[Test]
public void SomeTest()
{
some code;
Thread.Sleep(2000);
more code;
}
}
}
The error is because webdriver doesn't have a waitForPageToLoad function.
And you dont need it with webdriver because it will automatically block after every action, untill the page loads completely. More details here .. WebDriver FAQ
But you can have custom waits, like wait for Elements to appear on page using WebDriverWait.

Using selenium web driver to run test on multiple browsers

I'm trying to run a same test across multiple browsers through for loop but it always run only on Firefox.
bros = ['FIREFOX','CHROME','INTERNET EXPLORER']
for bro in bros:
print "Running "+bro+"\n"
browser = webdriver.Remote(
command_executor='http://10.236.194.218:4444/wd/hub',
desired_capabilities={'browserName': bro,
'javascriptEnabled': True})
browser.implicitly_wait(60000)
browser.get("http://10.236.194.156")
One interesting observation; when I include the parameter platform: WINDOWS it's running only on Internet Explorer.
Does Selenium Webdriver works this way or my understanding is wrong?
I actually have done this in java, the following works well for me:
...
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
...
DesiredCapabilities[] browsers = {DesiredCapabilities.firefox(),DesiredCapabilities.chrome(),DesiredCapabilities.internetExplorer()};
for(DesiredCapabilities browser : browsers)
{
try{
System.out.println("Testing in Browser: "+browser.getBrowserName());
driver = new RemoteWebDriver(new URL("http://127.0.0.1:4444/wd/hub"), browser);
...
You will need to adapt this of course if you're writing your tests in a different language, I know it's possible in Java, not sure about otherwise.
Also, I agree with what you're trying to do, I think it is much better to have a class that runs the same tests with different browsers, instead of duplicating code many times over and being inelegant. If you are doing this in Java/other codes, I also highly suggest using a Page Object.
Good luck!
So if I got you right, you have one testcase and want this to be tested against different browsers.
I don't think a loop is a good idea even if it's possible (I don't know atm).
The idea is to be able to test every testcase standalone on the run with a specific browser (thats the JUnit philosophy), not to run all in order to get to that specific browser .
So you need to create a WebDriver with the specific browser and the specific testcase.
I suggest you seperate testcases by creating a testcase-class file for each browser.
Like: FirefoxTestOne.java, IeTestOne.java, ChromeTestOne.java .
Note that you can add multiple firefox tests in the FirefoxTestOne without problems. Theres no guarantee that they will be executed in a particular order through (JUnit philosophy).
For links and tutorials ask google. There are already looooots of examples written.
You will have to generate multiple test classes (or webdriver instances) with the chosen browsers.
A Webdriver is defined with one browser.
As Coretek said you need multiple webdriver instances. You will need to run the selenium-server .jar file and provide each one with an argument specifying the browser you want that instance of the server to run.
The argument for Internet Explorer is *iexplore, the argument for firefox is *firefox and the argument for chrome is *chrome. These are -forcedBrowserMode arguments. Otherwise selenium won't know what it should be running against. You may need to use *iexploreProxy for your tests, sometimes it works better than the *iexplore mode.
Check out this link for more arguments that may be useful:
http://seleniumforum.forumotion.net/t89-selenium-server-command-options-while-starting-server
This way (attached url) worked for me.
http://blog.varunin.com/2011/07/running-selenium-tests-on-different.html
The following point is different from the example.
#Parameters
public static List data() {
return Arrays.asList(new Object[][]{{"firefox"},{"ie"}});
}
#Before
public void setUp() throws Exception {
System.out.println("browser: " + browser);
if(browser.equalsIgnoreCase("ie")) {
System.setProperty("webdriver.ie.driver", "IEDriverServer64.exe");
driver = new InternetExplorerDriver();
} else if(browser.equalsIgnoreCase("firefox")) {
driver = new FirefoxDriver();
You can use TestNG for this
combination of selenium + testng gives you a batter result for this
just by adding parameters attribute you can do this
Have you considered using the composite design pattern to create a CompositeWebDriver that actually runs multiple component WebDriver (such as chrome, gecko,...)? To this end, you would extend the WebDriver class with a new one (e.g. CompositeWebDriver) that just delegates his calls to all the actual WebDrivers.
This could also be done with various instances of RemoteWebDriver as components.

Resources