I'm using Selenium-serenity for my integration test. By default selenium integrate FirefoxDriver for the WebDriver, but now what I'm trying to do is use PhantomJS. I could not find so far how to set the driver properly after being initialized.
So far what I did is override the getDriver() method of pageObject and return the phantomJs webDriver
private static WebDriver webDriver;
#Override
public WebDriver getDriver() {
if (webDriver == null) {
DesiredCapabilities caps = new DesiredCapabilities();
caps.setJavascriptEnabled(true);
caps.setCapability(PhantomJSDriverService.PHANTOMJS_EXECUTABLE_PATH_PROPERTY, "/Users/pabloperezgarcia/Downloads/phantomjs");
webDriver = new PhantomJSDriver(caps);
setDriver(webDriver);
}
return webDriver;
}
But the problem is that every single action over webdriver is not propagate over the other pages because of course we are only returning the singleton webDriver, but not the super.getDriver().
My question is how can I set properly the webdriver on serenity to be share the state between multiple pages object, which are new instances.
With Firefox seems work perfectly.
You need to set the webdriver.driver property to phantomjs. With serenity this can be passed via command line, defined in a properties file, or annotated in the code. You may also need to specify the location of the phantomjs driver via a system property -Dphantomjs.binary.path=path/to/driver.
You mentioned you're using annotations, have you tried #Managed(driver="phantomjs")?
You could also pass via command line (in your IDE it would be in run configuration) -Dwebdriver.driver=phantomjs
Be aware if you are running your tests remotely you may also need to set the phantomjs.webdriver property to the port you want to run on.
You can also set properties via maven:
<properties>
<webdriver.driver>phantomjs</webdriver.driver>
</properties>
and then in your failsafe plugin define the system property
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.18</version>
<configuration>
<systemProperties>
<webdriver.driver>${webdriver.driver}</webdriver.driver>
</systemProperties>
</configuration>
</plugin>
If you want to define a custom driver provider, you need to make sure you implement DriverSource and define the following properties webdriver.driver,
webdriver.provided.type, webdriver.provided.mydriver, thucydides.driver.capabilities
Serenity documentation: http://thucydides.info/docs/serenity-staging/
Related
I have below feature files (Separate feature files) in src/test/resources/feature/ and I would like to run them in parallel. Like: One feature file has to execute in chrome and another one has to execute in firefox as mentioned #Tags name.
Feature: Refund item
#chrome
Scenario: Jeff returns a faulty microwave
Given Jeff has bought a microwave for $100
And he has a receipt
When he returns the microwave
Then Jeff should be refunded $100
Feature: Refund Money
#firefox
Scenario: Jeff returns the money
Given Jeff has bought a microwave for $100
And he has a receipt
When he returns the microwave
Then Jeff should be refunded $100
Can somebody assist me to achieve this.I'm using cucumber-java 1.2.2 version, and AbstractTestNGCucumberTests using as runner. Also, let me know how can I create a Test Runner dynamically by using feature files and make them run in parallel.
Update: 4.0.0 version is available at maven central repository with bunch of changes.for more details go here.
Update: 2.2.0 version is available at maven central repository.
You can use opensource plugin cucumber-jvm-parallel-plugin which has many advantages over existing solutions. Available at maven repository
<dependency>
<groupId>com.github.temyers</groupId>
<artifactId>cucumber-jvm-parallel-plugin</artifactId>
<version>2.1.0</version>
</dependency>
First you need to add this plugin with required configuration in your project pom file.
<plugin>
<groupId>com.github.temyers</groupId>
<artifactId>cucumber-jvm-parallel-plugin</artifactId>
<version>2.1.0</version>
<executions>
<execution>
<id>generateRunners</id>
<phase>generate-test-sources</phase>
<goals>
<goal>generateRunners</goal>
</goals>
<configuration>
<!-- Mandatory -->
<!-- comma separated list of package names to scan for glue code -->
<glue>foo, bar</glue>
<outputDirectory>${project.build.directory}/generated-test-sources/cucumber</outputDirectory>
<!-- The directory, which must be in the root of the runtime classpath, containing your feature files. -->
<featuresDirectory>src/test/resources/features/</featuresDirectory>
<!-- Directory where the cucumber report files shall be written -->
<cucumberOutputDir>target/cucumber-parallel</cucumberOutputDir>
<!-- comma separated list of output formats json,html,rerun.txt -->
<format>json</format>
<!-- CucumberOptions.strict property -->
<strict>true</strict>
<!-- CucumberOptions.monochrome property -->
<monochrome>true</monochrome>
<!-- The tags to run, maps to CucumberOptions.tags property you can pass ANDed tags like "#tag1","#tag2" and ORed tags like "#tag1,#tag2,#tag3" -->
<tags></tags>
<!-- If set to true, only feature files containing the required tags shall be generated. -->
<filterFeaturesByTags>false</filterFeaturesByTags>
<!-- Generate TestNG runners instead of default JUnit ones. -->
<useTestNG>false</useTestNG>
<!-- The naming scheme to use for the generated test classes. One of 'simple' or 'feature-title' -->
<namingScheme>simple</namingScheme>
<!-- The class naming pattern to use. Only required/used if naming scheme is 'pattern'.-->
<namingPattern>Parallel{c}IT</namingPattern>
<!-- One of [SCENARIO, FEATURE]. SCENARIO generates one runner per scenario. FEATURE generates a runner per feature. -->
<parallelScheme>SCENARIO</parallelScheme>
<!-- This is optional, required only if you want to specify a custom template for the generated sources (this is a relative path) -->
<customVmTemplate>src/test/resources/cucumber-custom-runner.vm</customVmTemplate>
</configuration>
</execution>
</executions>
</plugin>
Now add below plugin just below above plugin which will invoke runner classes generated by above plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19</version>
<configuration>
<forkCount>5</forkCount>
<reuseForks>true</reuseForks>
<includes>
<include>**/*IT.class</include>
</includes>
</configuration>
</plugin>
Above two plugins will do magic for cucumber test running in parallel (provided you machine also have advanced hardware support).
Strictly provided <forkCount>n</forkCount> here 'n' is directly proportional to 1) Advanced Hardware support and 2) you available nodes i.e. registered browser instances to HUB.
One major and most important changes is your WebDriver class must be SHARED and you should not implement driver.quit() method, as closing is take care by shutdown hook.
import cucumber.api.Scenario;
import cucumber.api.java.After;
import cucumber.api.java.Before;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.events.EventFiringWebDriver;
public class SharedDriver extends EventFiringWebDriver {
private static WebDriver REAL_DRIVER = null;
private static final Thread CLOSE_THREAD = new Thread() {
#Override
public void run() {
REAL_DRIVER.close();
}
};
static {
Runtime.getRuntime().addShutdownHook(CLOSE_THREAD);
}
public SharedDriver() {
super(CreateDriver());
}
public static WebDriver CreateDriver() {
WebDriver webDriver;
if (REAL_DRIVER == null)
webDriver = new FirefoxDriver();
setWebDriver(webDriver);
return webDriver;
}
public static void setWebDriver(WebDriver webDriver) {
this.REAL_DRIVER = webDriver;
}
public static WebDriver getWebDriver() {
return this.REAL_DRIVER;
}
#Override
public void close() {
if (Thread.currentThread() != CLOSE_THREAD) {
throw new UnsupportedOperationException("You shouldn't close this WebDriver. It's shared and will close when the JVM exits.");
}
super.close();
}
#Before
public void deleteAllCookies() {
manage().deleteAllCookies();
}
#After
public void embedScreenshot(Scenario scenario) {
try {
byte[] screenshot = getScreenshotAs(OutputType.BYTES);
scenario.embed(screenshot, "image/png");
} catch (WebDriverException somePlatformsDontSupportScreenshots) {
System.err.println(somePlatformsDontSupportScreenshots.getMessage());
}
}
}
Considering you want to execute more than 50 threads i.e. same no of browser instances are registered to HUB but Hub will die if it doesn't get enough memory therefore to avoid this critical situation you should start hub with -DPOOL_MAX=512 (or larger) as stated in grid2 documentation.
Really large (>50 node) Hub installations may need to increase the jetty threads by setting -DPOOL_MAX=512 (or larger) on the java command line.
java -jar selenium-server-standalone-<version>.jar -role hub -DPOOL_MAX=512
Cucumber does not support parallel execution out of the box.
I've tried, but it is not friendly.
We have to use maven's capability to invoke it in parallel. Refer link
Also there is a github project which uses custom plugin to execute in parallel.
Refer cucumber-jvm-parallel-plugin
If all you are expecting is to be able to run multiple features in parallel, then you can try doing the following :
Duplicate the class AbstractTestNGCucumberTests in your test project and set the attribute parallel=true to the #DataProvider annotated method.
Since the default dataprovider-thread-count from TestNG is 10 and now that you have instructed TestNG to run features in parallel, you should start seeing your feature files get executed in parallel.
But I understand that Cucumber reporting is inherently not thread safe, so your reports may appear garbled.
I achieved cucumber parallelism using courgette-jvm . It worked out of the box and run parallel test at scenario level
Simply inlclude similar runner class in cucumber. My tests are further using RemoteWebdriver to open multiple instances on selenium grid. Make sure grid is up and running and node is registered to the grid.
import courgette.api.CourgetteOptions;
import courgette.api.CourgetteRunLevel;
import courgette.api.CucumberOptions;
import courgette.api.testng.TestNGCourgette;
import io.cucumber.testng.AbstractTestNGCucumberTests;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
#Test
#CourgetteOptions(
threads = 10,
runLevel = CourgetteRunLevel.SCENARIO,
rerunFailedScenarios = true,
rerunAttempts = 1,
showTestOutput = true,
reportTitle = "Courgette-JVM Example",
reportTargetDir = "build",
environmentInfo = "browser=chrome; git_branch=master",
cucumberOptions = #CucumberOptions(
features = "src/test/resources/com/test/",
glue = "com.test.stepdefs",
publish = true,
plugin = {
"pretty",
"json:target/cucumber-report/cucumber.json",
"html:target/cucumber-report/cucumber.html"}
))
class AcceptanceIT extends TestNGCourgette {
}
RemoteWebdriver config is
protected RemoteWebDriver createDriver() throws MalformedURLException , IOException {
Properties properties = new Properties();
ClassLoader loader = Thread.currentThread().getContextClassLoader();
String hubURL = "http://192.168.1.7:65299/wd/hub";
System.setProperty("webdriver.gecko.driver", "/Users/amit/Desktop/amit/projects/misc/geckodriver");
FirefoxProfile profile = new FirefoxProfile();
DesiredCapabilities capabilities = DesiredCapabilities.firefox();
capabilities.setCapability(FirefoxDriver.PROFILE, profile);
capabilities.setPlatform(Platform.ANY);
FirefoxOptions options = new FirefoxOptions();
options.merge(capabilities);
driver.set(new RemoteWebDriver(new URL(hubURL),options));
return driver.get();
}
To take maximum advantage of TestNG you can use Testng's third party extension QAF framework. It supports multiple bdd syntax including gherkin using GherkinFactory.
While using BDD with QAF, you can take advantage of each TestNG features, including data-providers, parallel execution configuration in different ways (groups/tests/methods), TestNG listeners.
QAF considers each scenario as TestNG test and Scenario Outline as TestNG data-driven test. As qaf provides driver management and resource management in-built, you don't need to write single line of code for driver management or resource management. All you need to do is create TestNG xml configuration file as per your requirement either to run parallel methods (scenarios) or groups or xml test on one or more browser.
It enables different possible configuration combinations. Below is the xml configuration to address this question which will run scenarios in two browsers and in parallel. You can configure number of threads for each browser as standard TestNG xml configuration as well.
<suite name="AUT Test Automation" verbose="0" parallel="tests">
<test name="Test-on-chrome">
<parameter name="scenario.file.loc" value="resources/features" />
<parameter name="driver.name" value="chromeDriver" />
<classes>
<class name="com.qmetry.qaf.automation.step.client.gherkin.GherkinScenarioFactory" />
</classes>
</test>
<test name="Test-on-FF">
<parameter name="scenario.file.loc" value="resources/features" />
<parameter name="driver.name" value="firefoxDriver" />
<classes>
<class name="com.qmetry.qaf.automation.step.client.gherkin.GherkinScenarioFactory" />
</classes>
</test>
</suite>
More over the latest BDDTestFactory2 supports syntax that is derived from QAF BDD, Jbehave and gherkin. It supports meta-data from qaf bdd as tags and examples from gherkin. You can take benefit of inbuilt data-providers to provide test data in XML/JSON/CSV/EXCEL/DB using meta-data in BDD.
EDIT:
Cucumber-5 users can take benefit of qaf-cucumber support library.
Since v4 of Cucumber you can do this without extensions of plugins.
https://github.com/cucumber/cucumber-jvm/tree/main/cucumber-testng#parallel-execution
Cucumber TestNG supports parallel execution of scenarios. Override the
scenarios method to enable parallel execution.
public class RunCucumberTest extends
AbstractTestNGCucumberTests {
#Override
#DataProvider(parallel = true)
public Object[][] scenarios() {
return super.scenarios();
}
}
Maven Surefire plugin configuration for parallel execution
<plugins> <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<properties>
<property>
<name>dataproviderthreadcount</name>
<value>${threadcount}</value>
</property>
</properties>
</configuration>
</plugin>
</plugins>
Where dataproviderthreadcount is the default number of threads to use
for data providers when running tests in parallel.
I am writing a test automation framework that runs some tests on devices using AppiumDriver and some on the web using WebDriver.
Currently I am declaring two different drivers as shown below:
public static AppiumDriver appDriver = null;
public static RemoteWebDriver webDriver = null;
If the test runs on a device it uses appDriver and if it runs on the web it uses webDriver.
However this causes problems for shared methods such as driver.quit....I have to have more code to handle both types of driver...(e.g. if device test appDriver.quit, if web webDriver.quit).
Is there a way to just declare one driver (called driver) that can be cast to Appiumdriver or Webdriver as required by the test?
I could then use driver.quit and this would work regardless of whether the test is a device test or a web test?
Thanks for any help.
The hierarchy of Selenium is as follows. More details here
interface Webdriver extends SearchContext{
}
class RemoteWebDriver implements Webdriver{
}
class ChromeWebDriver extends RemoteWebDriver{
}
class FirefoxWebDriver extends RemoteWebDriver{
}
The hierarchy of Appium is as follows. More details here
java.lang.Object
org.openqa.selenium.remote.RemoteWebDriver
io.appium.java_client.AppiumDriver<T>
So I suggest you can create instance of RemoteWebDriver class and then use it accordingly for web(selenium) and mobile(appium).
Could you please look at my problem and give any advice to its solving.
I use JUnit4 and selenium 2 WebDriver.
So, I have class to run JUnit suite:
#RunWith(Suite.class)
#Suite.SuiteClasses({className1.class, clasName2.class})
public class TestSuite
{
public static TestSuite suite()
{
TestSuite suite = new TestSuite();
suite.addTest(new JUnit4TestAdapter(className1.class));
suite.addTest(new JUnit4TestAdapter(className2.class));
return suite;
}
}
each class contains #Test method and extends BaseClass that sets in #BeforeClass parameters (through DesiredCapabilities) to run suite on BrowserStack machines:
public class MyTestBase{
static protected WebDriver driver;
private boolean acceptNextAlert = true;
protected static StringBuffer verificationErrors = new StringBuffer();
#BeforeClass
public static void setUp() throws Exception {
DesiredCapabilities capability = DesiredCapabilities.firefox();
capability.setPlatform(Platform.WINDOWS);
capability.setCapability("build", "JUnit - Sample");
capability.setCapability("acceptSslCerts", "true");
capability.setCapability("browserstack.debug", "true");
driver = new RemoteWebDriver(
new URL("http://username:accesskey#hub.browserstack.com/wd/hub"),
capability);
driver.manage().timeouts().implicitlyWait(40, TimeUnit.SECONDS);
}
/* other code */
}
So, could you please help me with the next:
1) I need to create configuration file and use its parameters to run my TestSuite on different browsers in BrowserStack. Any examples of .xml file to do it will be appreciated.
2) And also how do I need to modify my TestSuite.class to use .xml file parameters.
3) My TestSuite.class consists of many .class with #Test method in each. Each class extends MyTestBase.class where annotations #BeforeClass and #AfterClass are located, but when I run TestSuite new browser has been launched for each class in TestSuite and it's a very big problem for me. What can I do for running browser once for all #Test methods across all classes in TestSuite. I know that #BeforeClass works for all #Test methods inside one class, but what should be done if there are may classes? In TestNG there is #BeforeSuite solves this problem.
Sorry, for so many questions, but I've tried a lot and didn't succeed in this :(
Thanks a lot!
You asked a lot of questions concerning different topics. I will try to sort things out.
Reusing a browser and not opening a new one for every test class
This can only be achieved if you instantiate your WebDriver once and use that object in all your tests. So don't instantiate your browser in the #BeforeClass method of your tests.
How do you initialise your WebDriver?
In the very first test class of your test suite. That might be a dedicated test just for opening the browser. Or you could include this functionality in all of your test and have to check, if the browser had already been initialised or not.
How to reuse a WebDriver object and share it between test classes?
I'd propose to create a Singleton that stores a WebDriver object. This way all tests can access it. However, it takes some more effort to make this thread-safe - in case your run your tests in parallel.
Running your tests with different browsers
You should make your tests #Parameterized and expect a set of WebDriver objects as parameters to execute.
Combining both: Different browsers and reusing browsers between tests
This will likely lead to a point where you would like to define parameters for your test suite. However, in standard JUnit 4 you can't do this.
I recommend to use the ParameterizedSuite runner from this library.
So currently I am doing something like this to do cross browser testing:
#DataProvider(name="foo")
public Object[][] getDrivers() {
DesiredCapabilities firefoxCapabs = DesiredCapabilities.firefox();
capabillities.setCapability("version", "26");
capabillities.setCapability("platform", Platform.WINDOWS);
DesiredCapabilities chromeCapabs = ....
....
DesiredCapabilities ieCapabs = ...
....
return new Object[][]{
{new RemoteWebDriver(url, firefoxCapabs)},
{new RemoteWebDriver(url, chromeCapabs)},
......
};
}
#Test(dataProvider="foo")
public void testSomething(WebDriver driver) {
//some test
}
This seems extremely inefficient as I am basically creating and destroying these WebDriver objects every time I run a test. Is there no way to do something like this at least at the TestSuite level so that I am not generating and destroying these objects for every test. I would like something like below. I am aware that you cannot have a DataProvider for #BeforeSuite methods!
public class TestSuite{
public static WebDriver driver;
#BeforeSuite(dataProvider="foo")
public void setDriver(WebDriver driver) {
this.driver = driver;
}
}
public class TestClass {
private WebDriver driver;
#BeforeTest
public void getDriver() {
this.driver = TestSuite.driver;
}
#Test
public void myTest() {
//use this.driver to do testing stuff
}
}
Are there options I am not seeing to do something like this?
Sauce Labs On Demand has a great plugin for Jenkins (https://saucelabs.com/jenkins/5). Their approach is pretty simple: you check/uncheck what OSs and browsers you to test and Jenkins sets environment variables for your tests to pick up. Below is a complete example of using Spring's #Configuration:
package com.acme.test;
import java.net.MalformedURLException;
import java.net.URL;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.core.env.Environment;
#Configuration
public class SauceLabsWebDriverConfiguration {
#Autowired private Environment environment;
#Bean
#Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public WebDriver webDriver() throws MalformedURLException {
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("version", environment.getProperty("SELENIUM_VERSION", "17.0.1"));
capabilities.setCapability("platform", environment.getProperty("SELENIUM_PLATFORM", "XP"));
capabilities.setCapability("browserName", environment.getProperty("SELENIUM_BROWSER", "firefox"));
String username = environment.getProperty("SAUCE_USER_NAME", "enter_your_username_here");
String accessKey = environment.getProperty("SAUCE_API_KEY", "enter_your_api_here");
return new RemoteWebDriver(new URL("http://" + username + ":" + accessKey + "#ondemand.saucelabs.com:80/wd/hub"), capabilities);
}
}
Sauce Labs has some free plans, but if you don't want to use them, you should be able to switch out the last part that constructs the URL ("http://" + username + ":" + accessKey + "#ondemand.saucelabs.com:80/wd/hub") the actual server URL you want to point to ("http://mydomain.com").
The trick is basically to replace hard-coded browser/capability names with environment provided ones and then have your build runner (ant/maven/etc) set environment variables for each of the OS/browser combos you want to test and "loop" over those somehow. SauceLabs plugins just makes it easy to do the looping. You can still provide default fallback values in case you want to run a simple local test.
// Before
DesiredCapabilities firefoxCapabs = DesiredCapabilities.firefox();
capabillities.setCapability("version", "26");
capabillities.setCapability("platform", Platform.WINDOWS);
// After
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("version", environment.getProperty("SELENIUM_VERSION", "17.0.1"));
capabilities.setCapability("platform", environment.getProperty("SELENIUM_PLATFORM", "XP"));
capabilities.setCapability("browserName", environment.getProperty("SELENIUM_BROWSER", "firefox"));
Hope it helps.
Two ways to implement this
1) Since you are using a Suite, you can create two tests that will run at the start of the suite and the end , one will setup Webdriver and store it in a global value; which each test class can later access , and the second will close the webdriver.
2) You can use dependency injection to setup webdriver as a singleton/global value and inject it to each test
http://testng.org/doc/documentation-main.html#dependency-injection
Here's something you can try:
Use the ITestListener. Implement the onStart and onFinish methods to create threadlocal variables for your driver based on the param value
i.e.
In onStart(context), fetch your parameter value using
context.getCurrentXmlTest().getParameter("something")
Depending on the param value populate the threadlocal value with appropriate initialized driver
ThreadLocal<WebDriver> threadDriver = new ThreadLocal<WebDriver>()
In your xml pass the browser as parameter for individual test tags and set parallel=tests
<test name="1" >
<parameter name="browser" value="ff"></parameter>
<classes>
<class name="com.nv.test.testngtests.Eq"/>
</classes>
</test>
<test name="2" >
<parameter name="browser" value="chrome"></parameter>
<classes>
<class name="com.nv.test.testngtests.Eq"/>
</classes>
</test>
You can take it at suite level too with ISuiteListener, but I think with the test approach you atleast get a chance to have some kind of parallelism
Two ways I see to fix this problem:
Have a different instance of the driver for each class, and use a #BeforeClass to create the driver (I personally do this, because it allows me to run all of my classes in parallel)
Construct your driver in your class's constructor, and use a #Factory.
Both of these solutions will create a driver per class. If you want to have a single set of drivers for your entire suite, create and store an Object[][] statically, and use it in your #dataProvider.
What I have did in my framework is to use configuration file(java properties file) to to set the browser parameter.
in your project you can create different classes for Browsers for example IE,Firefox etc.. inside this classes let have the functions to create webdriver with desired capabilities.
Now create a Driver class in which you can create function to initilize webdriver from your browser class as per the input from your proerties file. for example.
you can save properties file with Framework.properties name and inside the file add line like below
Browser=Firefox
'Browser=internetExplorer
...so on
To read this property file use java.util.Properties like below.
Properties prop = new Properties();
FileInputStream stream = new FileInputStream("path to property file");
prop.load(stream);
String browser = prop.getProperty(attribute);
stream.close();
Now use this browser parameter in your Driver class as below.
switch (Browser) {
case "FireFox":
return FireFox.initializeFireFoxDriver();
case "InternetExplorer":
return IE.initializeInternetExplorerDriver();
case "Chrome":
return Chrome.initializeChromeDriver();
case "Safari":
return Safari.initializeSafariDriver();
default:
break;
}
Call this class method in your fixture setup and it will start browser instance as per mentioned in properties file.
In case if you don't want to use property file method please use #parameter option in testng.xml for running test suite for passing browser name.
Assuming you are making use of CI, so you can maintain a configuration file that maintains what browser, base URL you should intake for performing a test over test suite.
This configuration can be maintained in a properties file that is always read in #BeforeSuite and accordingly you can load the WebDriver with DesiredCapabilities
Now being in a CI, you can have multiple projects differentiating browser and each can be run parallel/simultaneously, helping you use the resources efficiently and each project will override the configuration file with the required data.
Have a look to Selenium Grid. Never used myself but as far as I understand your question it matches your needs. Selenium Grid allow you to run your selenium test case on different OS/browser combination.
More info on http://docs.seleniumhq.org/docs/07_selenium_grid.jsp and http://code.google.com/p/selenium/wiki/Grid2
I am sorry if this is already answered, I tried to find a solution and still not getting anything.
I am working in Eclipse and Selenium webdriver and running the code via MAVEN.
My problem is that Maven continues running forever if an error was found, Selenium driver is not closed until I close the browser's window.
I can do it manually if anything happens in local, but the problem is when I try to use Jenknins, If anything fails, Jenkins job is running until I stop it.
Can you please help me?
Thanks in advance.
The important thing is to call WebDriver.quit() as you finish testing.
Usually in JUnit, this usually means calling it in one of these places:
a method or class annotated with #After or #AfterClass,
a property or class annotated with #Rule or #ClassRule,
a RunListener class, via the testFinished() or testRunFinished() methods,
a suitable runner class or
static teardown code.
You should choose the opposite to wherever you create your driver object. If all your tests are Selenium WebDriver ones and if you intend to run them sequentially in a single browser window (I think that this is the most common situation for smallish projects), then a single RunListener can hide this code nicely. As an example:
public class WebDriverContext extends RunListener {
public static WebDriver DRIVER; // Pretending to be final
public void testRunStarted(Description descr) {
DRIVER = new FirefoxDriver();
}
public void testRunFinished(Result result) {
DRIVER.quit();
}
}
(Credit to the OP for this answer, in his comment above. He's apparently gone from SO now, so he's not going to be able to post his answer here. I've also expanded it a fair bit.)