Testing selenium in different browsers using TestNG

So, I'm currently doing something similar 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 basically create and destroy these WebDriver objects every time I run the test. Is there no way to do something like this, at least at the TestSuite level, so that I do not generate and destroy these objects for each test. I would like something like below. I know 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 any options that I don’t see to do something like this?

+6
source share
7 answers

Sauce Labs On Demand has a great plugin for Jenkins ( https://saucelabs.com/jenkins/5 ). Their approach is quite simple: you check / take off which OS and browsers you test, and Jenkins sets environment variables for your tests. The following is a complete example of using Spring @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 do not want to use them, you should be able to disable the last part, which creates the URL ("http: //" + username + ":" + accessKey + "@ ondemand.saucelabs .com: 80 / wd / hub ") the actual URL of the server you want to point to (" http://mydomain.com ").

The trick is basically replacing the names of hard-coded browsers / features with the provided environments, and then you have a build runner (ant / maven / etc) that sets the environment variables for each combo version of the OS / browser that you want to test and "loop" over them somehow. SauceLabs plugins simply simplify looping. You can still provide fallback defaults if 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 this helps.

+4
source

Two ways to implement this

1) Since you are using Suite, you can create two tests that will run at the beginning of the package and at the end, one will install Webdriver and store it in a global value; which each test class can receive later, and the second will close webdriver.

2) You can use dependency injection to configure webdriver as a single-point / global value and inject it into each test http://testng.org/doc/documentation-main.html#dependency-injection

+1
source

Here you can try: Use ITestListener. Implement the onStart and onFinish methods to create threadlocal variables for your driver based on the parameter value i.e. in onStart (context), select the parameter value using

 context.getCurrentXmlTest().getParameter("something") 

Depending on the value of the parameter, enter the threadlocal value with the corresponding initialized driver

 ThreadLocal<WebDriver> threadDriver = new ThreadLocal<WebDriver>() 

In 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 the bundle level also with ISuiteListener, but I think that with the test approach you get a chance to get some kind of parallelism

+1
source

Two ways I see to fix this problem:

  • Have a different driver instance for each class and use @BeforeClass to create the driver (I personally do this because it allows me to run all my classes in parallel)
  • Create your driver in your class constructor and use @Factory .

Both of these solutions will create a driver for each class. If you want to have one set of drivers for the whole package, create and save Object[][] statically and use it in @dataProvider .

0
source

What I did in my structure was to use the configuration file (java properties file) to set the browser parameter. in your project you can create different classes for browsers, for example IE, Firefox, etc. Inside these classes, you can create functions to create a webdriver with the desired capabilities.

Now create a driver class in which you can create a function to initialize the webdriver from your browser class according to the input from the proerties file. eg.

you can save the properties file with the name Framework.properties and inside the line to add the file as shown below

  Browser=Firefox 'Browser=internetExplorer ...so on 

To read this properties file, use java.util.Properties , as shown 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 option in your driver class, as shown 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 device’s settings and start the browser instance as specified in the properties file.

If you do not want to use the property file method, use the @parameter parameter in testng.xml to run the test suite to pass the browser name.

0
source

Assuming you are using CI so that you can support a configuration file that supports which browser, the base URL that you should use to test the test suite.

This configuration can be supported in the properties file, which is always read in @BeforeSuite and, accordingly, you can load WebDriver using DesiredCapabilities

Now, being in CI, you can have several projects that distinguish between the browser, and each of them can run in parallel / simultaneously, which helps to efficiently use resources, and each project will redefine the configuration file with the required data.

0
source

Look at the selenium grid. I have never used myself, but as far as I understand your question, it meets your needs. Selenium Grid allows you to run a test case for selenium in different OS / browser combinations.

Additional information about http://docs.seleniumhq.org/docs/07_selenium_grid.jsp and http://code.google.com/p/selenium/wiki/Grid2

0
source

All Articles