Using selenium web driver to run test on multiple browsers - browser

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.

Related

Undefined steps after running test from TestRunner class

I have a very strange situation, I have created Features and Scenarios in the feature file and corresponding step definitions and methods in the separate class.
I have run tests by running a feature file, and everything was fine, all tests were green.
But, when I run tests from TestRunner class, I got the following message:
Undefined step: Given I am on the Facebook Login page and suggested code.
You can implement missing steps with the snippets below:
#Given("^I am on the Facebook Login page$")
public void i_am_on_the_Facebook_Login_page() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
I have noticed that the suggested method have underscore:
(i_am_on_the_Facebook_Login_page())
but my methods do not have underscore
(iAmOnTheFacebookLoginPage())
Does anybody have an idea why this happens? I can't run tests now even from the feature file.
Recently, I have started using Mac and IntelliJ instead of Windows and Eclipse.
Is it possible that IntelliJ causes the problem?
P.S. I have used the option "Create step definition" from IntelliJ
ah...I figured out what the problem was...I forgot to put this piece of code
snippets = SnippetType.CAMELCASE
in CucumberOptions.
So, when I put this line of code here
#CucumberOptions(
plugin = {"pretty"},
features = {"src/test/resources/features"}, glue = {"/java/stepDefinitions"}, snippets = SnippetType.CAMELCASE)
everything works just fine.
It is possible your features folder is not in the build path (being a test folder) so Cucumber is unable to find it. Try this.

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!

Execute Spock Test in Different Environments

I have a Selenium test, which is executed with the help of Spock framework. In general it looks like this:
class SeleniumSpec extends Specification {
URL remoteAddress // Address of SE grid
Capabilities caps // Desired capabilities
WebDriver driver // Web driver
def setup() {
driver = new RemoteWebDriver(remoteAddress, caps)
}
def "some test" () {
expect:
driver.findElement(By.cssSelector("p.someParagraph")).text == 'Some text'
}
// other tests go here ...
}
The point here is, that my specification describes behavior of some component (in most cases - web views/pages). So the methods are expected to implement some business-relative logic (smth. like 'click on button and expect message in another field); but another thing, I would like to test, is to ensure that behavior is exactly the same in all browsers (capabilities).
To achieve this in 'ideal' world, I'd like to have a mechanism to specify, that a particular test class should be used several times, but with some different parameters. But for now, I see an ability to apply data sets only for a single method.
I came up only with several ideas to implement this (according to my current knowledge regarding Spock framework):
Use a list of drivers and execute each action over all list members. So each call to 'driver' will be replaced with 'drivers.each { it }' invocation. This approach, on the other hand, makes it hard to exactly discover, which of drivers failed the test.
Use method parameters and data sets to initiate a fresh copy of web driver on each iteration. This approach seems more logical according to Spock philosophy, but it requires a heavy operation of driver and web application initialization to be performed every time. It also removes ability to perform 'step-by-step' testing, since state of driver won't be preserved between test methods.
Combination of these approaches, when drivers are kept in a map, and each test invocation has exact name of driver to be used.
I'd appreciate, if anybody met this case and may come up with ideas, how to properly organize the testing process. Someone could also discover other approaches, or pros & contras of those above. Considering another test tool could be an option also.
You could create an abstract BaseSpec which contains all your features, but do not setup the driver in that spec. Then create a subspec for each different browser you want to test e.g.
class FirefoxSeleniumSpec extends BaseSeleniumSpec{
setupSpec(){
super.driver = new FirefoxDriver(...)
}
}
And then you can run all of the sub-specs to test all the browsers

Geb drive method

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.

How do you forbid users from doing evil things in Groovy Scripts?

I'm planning to integrate Groovy Script Engine to my game so it will give the game nice moddability but how do you prevent players from writing evil scripts like deleting all files on C: drive?
Groovy includes library like java.io.File by default so it will be pretty easy to do once they decided to write such scripts.
I guess I can't prevent users from writing something like while(1==1){} but is there anyway to at least not let them allow to delete/modify files or something dangerous for PCs?
There's a blog post by Cedric Champeau on customising the Groovy Compilation process, the second part of it shows how to use SecureASTCustomizer and CompilerConfiguration to limit what Scripts can do (and then has examples of defining your own AST checks for System.exit, etc...
Look into the SecurityContext class.
The Groovy Web Console appears to have already solved this problem, because it won't execute something like System.exit(1). The source code is available on GitHub, so you can see how they did it.
If you're not sure where to start, I suggest getting in touch with the author, who should be able to point you in the right direction.
I know this is a old question. I'm posting this as it might help some people out there.
We needed to allow end-users to upload Groovy scripts and execute them as part of a web application (that does a lot of other things). Our concern was that within these Groovy scripts, some users might attempt to read files from the file system, read System properties, call System.exit(), etc.
I looked into http://mrhaki.blogspot.com/2014/04/groovy-goodness-restricting-script.html but that will not prevent an expert Groovy developer from bypassing the checks as pointed out by others in other posts.
I then tried to get http://www.sdidit.nl/2012/12/groovy-dsl-executing-scripts-in-sandbox.html working but setting the Security Manager and Policy implementation at runtime did not work for me. I kept running into issues during app server startup and web page access. It seemed like by the time the Policy implementation took hold, it was too late and "CodeSources" (in Java-Security-speak) already took its access settings from the default Java policy file.
I then stumbled across the excellent white paper by Ted Neward (http://www.tedneward.com/files/Papers/JavaPolicy/JavaPolicy.pdf) that explained quite convincingly that the best approach (for my use case) was to set the Policy implementation on JVM startup (instead of dynamically later on).
Below is the approach that worked for me (that combines Rene's and Ted's approaches). BTW: We're using Groovy 2.3.10.
In the [JDK_HOME]/jre/lib/security/java.security file, set the "policy.provider" value to "com.yourcompany.security.MySecurityPolicy".
Create the MySecurityPolicy class:
import java.net.MalformedURLException;
import java.net.URL;
import java.security.AllPermission;
import java.security.CodeSource;
import java.security.PermissionCollection;
import java.security.Permissions;
import java.security.Policy;
import java.util.HashSet;
import java.util.Set;
public class MySecurityPolicy extends Policy {
private final Set<URL> locations;
public MySecurityPolicy() {
try {
locations = new HashSet<URL>();
locations.add(new URL("file", "", "/groovy/shell"));
locations.add(new URL("file", "", "/groovy/script"));
} catch (MalformedURLException e) {
throw new IllegalStateException(e);
}
}
#Override
public PermissionCollection getPermissions(CodeSource codeSource) {
// Do not store these in static or instance variables. It won't work. Also... they're cached by security infrastructure ... so this is okay.
PermissionCollection perms = new Permissions();
if (!locations.contains(codeSource.getLocation())) {
perms.add(new AllPermission());
}
return perms;
}
}
Jar up MySecurityPolicy and drop the jar in [JDK_HOME]/jre/lib/ext directory.
Add "-Djava.security.manager" to the JVM startup options. You do not need to provide a custom security manager. The default one works fine.
The "-Djava.security.manager" option enables Java Security Manager for the whole application. The application and all its dependencies will have "AllPermission" and will thereby be allowed to do anything.
Groovy scripts run under the "/groovy/shell" and "/groovy/script" "CodeSources". They're not necessarily physical directories on the file system. The code above does not give Groovy scripts any permissions.
Users could still do the following:
Thread.currentThread().interrupt();
while (true) {} (infinite loop)
You could prepend the following (dynamically at runtime) to the beginning of every script before passing it onto the Groovy shell for execution:
#ThreadInterrupt
import groovy.transform.ThreadInterrupt
#TimedInterrupt(5)
import groovy.transform.TimedInterrupt
These are expalined at http://www.jroller.com/melix/entry/upcoming_groovy_goodness_automatic_thread
The first one handles "Thread.currentThread().interrupt()" a little more gracefully (but it doesn't prevent the user from interupting the thread). Perhaps, you could use AST to prevent interupts to some extent. In our case, it's not a big issue as each Groovy script execution runs in its own thread and if bad actors wish to kill their own thread, they could knock themselves out.
The second one prevents the infinite loop in that all scripts time out after 5 seconds. You can adjust the time.
Note that I noticed a performance degradation in the Groovy script execution time but did not notice a significant degradation in the rest of the web application.
Hope that helps.

Resources