title: How do I limit threads on a TestNG dataprovider method used as a factory
body: <p>I'm using selenium to test a single page app. I'm loading the page in a <code>@beforeClass</code> method. Then running all the tests in the class. Then tearing down the driver in the <code>@afterClass</code> method.</p>
  
  <p>I've annotated my constructor as a <code>@factory</code> method using a <code>dataprovider</code> from a base class. The <code>dataprovider</code> is used to setup a collection of different browsers. </p>
  
  <p>I'm using crossbrowsertesting.com to run the tests, and I'm struggling to control the parallelization. I need to be able to control the maximum number of concurrent threads running at any one time (our current plan only allows for 2 simultaneous tests). And I want to ensure that parallelisation occurs at the dataprovider level. (i.e. I want a thread for each browser up to a maximum of 2 threads).</p>
  
  <p>I'm using a testng.xml file.</p>
  
  <pre><code>&lt;suite name="functional_tests" parallel="classes" thread-count="2"&gt;
      &lt;test name="com.mapov.functional_tests suite"&gt;
          &lt;classes&gt;
             &lt;class name="com.mapov.functional_tests.KiteTests" /&gt;
          &lt;/classes&gt;
  
      &lt;/test&gt;
  &lt;/suite&gt;
  </code></pre>
  
  <p>With a base class - </p>
  
  <pre><code>public class BaseTest {
  
      public BaseTest (String browser, String platform, String resolution, String browserDescription) {  
          userName = "myUsername";
          accessKey = "myKey"; 
          pageUrl = "http://test.mapov.com/hotels/benidorm";
          this.browserDescription = browserDescription;
  
          caps = new DesiredCapabilities();
          caps.setCapability("browser_api_name", browser);
          caps.setCapability("os_api_name", platform);
          caps.setCapability("screen_resolution", resolution);
          caps.setCapability("name", this.browserDescription);
          caps.setCapability("record_video", "false");
          caps.setCapability("record_network", "false");
          caps.setCapability("record_snapshot", "false");      
      }
  
      @DataProvider(parallel=true)
      public static Object[][] getBrowsers() {
          return new Object[][]{
              new Object[]{"MblSafari8.0", "iPadAir-iOS8Sim", "1024x768", "Ipad air, with safari 8"}, 
              new Object[]{"IE11", "Win10", "1280x1024", "IE11 on windows 10"},
              new Object[]{"Safari9", "Mac10.11", "1280x1024", "Safari 9 on Mac osx10.11"}, 
          };
      }
  
  
      @BeforeClass
      public void SetupDriver() {
          long id = Thread.currentThread().getId();
          try {
              URL remoteDriverURL = new URL("http://" + userName + ":" + accessKey + "@hub.crossbrowsertesting.com:80/wd/hub");
              driver = new RemoteWebDriver(remoteDriverURL, caps);
              driver.get(pageUrl);
              WebElement pager = (new WebDriverWait(driver, 30)).until(ExpectedConditions.visibilityOfElementLocated(By.id("pager")));
          } catch (MalformedURLException ex) {
              System.out.println(ex.getMessage());
          }
      }
  
      @AfterClass
      public void disposeOfDriver() {
          // quit the driver
      }
  }
  </code></pre>
  
  <p>And then an inheriting class with tests.</p>
  
  <pre><code>public class KiteTests extends BaseTest {
  
      @Factory(dataProvider = "getBrowsers")
      public KiteTests(String browser, String platform, String resolution, String description) {
          super(browser, platform, resolution, "Kite tests on " + description);
      }   
  
      @Test 
      public void testKitesAppear() {
          // test.
      }
  
      @Test
      public void testHotelNamePresent() {
         // test
      }
  
  }
  </code></pre>
  
  <p>If I remove the <code>parallel="classes" thread-count="2"</code> attributes from the suite node of the xml, then everything runs fine (just not in parallel).</p>
  
  <p>If I keep the parameters then I get the following error -</p>
  
  <pre><code>    FAILED CONFIGURATION: @BeforeClass SetupDriver
  org.openqa.selenium.WebDriverException: This account has reached it maxiumum number of concurrent selenium tests - please wait for a test to finish before starting a new test.
  Command duration or timeout: 668 milliseconds
  Build info: version: '2.48.2', revision: '41bccdd', time: '2015-10-09 19:55:52'
  System info: host: 'Ewen-Macbook.lan', ip: '192.168.1.65', os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.11', java.version: '1.8.0_45'
  Driver info: org.openqa.selenium.remote.RemoteWebDriver
      at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
      at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
      at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
      at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
      at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:206)
      at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:158)
      at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:647)
      at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriver.java:247)
      at org.openqa.selenium.remote.RemoteWebDriver.&lt;init&gt;(RemoteWebDriver.java:129)
      at org.openqa.selenium.remote.RemoteWebDriver.&lt;init&gt;(RemoteWebDriver.java:156)
      at com.mapov.functional_tests.BaseTest.SetupDriver(BaseTest.java:75)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:497)
      at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
      at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:564)
      at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:213)
      at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:138)
      at org.testng.internal.TestMethodWorker.invokeBeforeClassMethods(TestMethodWorker.java:175)
      at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:107)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
      at java.lang.Thread.run(Thread.java:745)
  </code></pre>