# Appium Tests Sharding with TestNG

**URL:** <https://discuss.appium.io/t/appium-tests-sharding-with-testng/45638>\
**Category:** Support\
**Created:** [March 23, 2025, 12:45pm UTC](https://discuss.appium.io/t/appium-tests-sharding-with-testng/45638 "2025-03-23T12:45:31Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Wasif\_Israr](https://discuss.appium.io/user_avatar/discuss.appium.io/wasif_israr/32/9595_2.png) [@Wasif\_Israr](https://discuss.appium.io/u/Wasif_Israr)\
**Post date:** [March 23, 2025, 12:45pm UTC](https://discuss.appium.io/t/appium-tests-sharding-with-testng/45638/1 "2025-03-23T12:45:31Z")

</div>

Hi,  
I am looking to implement test execution in such a way that If I have 100 tests across different JAVA classes. I can divide them to run on 4 devices in parallel to reduce the test execution time.

Currently I have set parallel=tests in my TestNG.xml file which runs Classes inside tag in parallel but that still takes a lot of time. Here’s my testng.xml:

```auto
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="POS Smoke Test Suite" parallel="tests" thread-count="2">
	<listeners>
		<listener class-name="reporting.Listeners"></listener>
	</listeners>
	<parameter name="environment" value="${environment}"></parameter>
  <test name="DashOrder">
	<parameter name="udid" value="${udid1}"></parameter>
	<parameter name="serverPin" value="${serverPin1}"></parameter>
	<parameter name="managerPin" value="${managerPin1}"></parameter>
	<parameter name="systemPort" value="${systemPort1}"></parameter>
	<parameter name="appiumPort" value="${appiumPort1}"></parameter>
	  <groups>
		  <run>
			  <include name="Smoke"></include>
		  </run>
	  </groups>
    <classes>
		<class name="tests.OrderTest">
	  </class>
		<class name="tests.CashDrawerTest"></class>
    </classes>
  </test>
 <!-- Test -->
   <test name="Test">
	<parameter name="udid" value="${udid2}"></parameter>
	<parameter name="serverPin" value="${serverPin2}"></parameter>
	<parameter name="managerPin" value="${managerPin2}"></parameter>
	<parameter name="systemPort" value="${systemPort2}"></parameter>
	<parameter name="appiumPort" value="${appiumPort2}"></parameter>
	  <groups>
		  <run>
			  <include name="Smoke"></include>
		  </run>
	  </groups>
    <classes>
	  <class name="tests.PaymentTest">
		  <methods>
			  <exclude name="verifyAmountAddedinDrawer"></exclude>
		  </methods>
	  </class>
		<class name="tests.QSRTests"></class>
    </classes>
  </test> <!-- Test -->
</suite> <!-- Suite -->

```

My Base Class containing BeforeMethod config method:

```auto
protected AndroidDriver getDriver() {
	    return driverThreadLocal.get();
	}

	protected void setDriver(AndroidDriver driver) {
	    driverThreadLocal.set(driver);
	}
	
	@BeforeMethod(alwaysRun=true)
	@Parameters({"udid","serverPin","systemPort","managerPin","appiumPort"})
	public void startApp(String udid,Method method,String serverPin,int systemPort,String managerPin,int appiumPort) {
		this.serverPin=serverPin;
		this.managerPin=managerPin;
		String env=FileUtility.readEnvironmentFromFile();
		UiAutomator2Options options1=new UiAutomator2Options();
		options1.setCapability("udid",udid);
		options1.setApp(System.getProperty("user.dir")+File.separator+"src"+File.separator+"test"+File.separator+"java"+File.separator+"resources"+File.separator+"pos-"+env+"-release.apk");
		options1.setCapability("autoGrantPermissions",true);
		options1.setSystemPort(systemPort);
		try {
			driver1=new AndroidDriver(new URL("http://localhost:"+appiumPort),options1);
			setDriver(driver1);
		}
		catch(Exception e) {
			getLogger().error("Driver1 Not Started "+e);	
		}
		getDriver().manage().timeouts().implicitlyWait(Duration.ofSeconds(5));
		getLogger().info("Starting test: " + method.getName());
	}

```

---

<div class="post-metadata">

**Author:** ![Aleksei](https://discuss.appium.io/user_avatar/discuss.appium.io/aleksei/32/6267_2.png) [@Aleksei](https://discuss.appium.io/u/Aleksei)\
**Post date:** [March 24, 2025, 2:52pm UTC](https://discuss.appium.io/t/appium-tests-sharding-with-testng/45638/2 "2025-03-24T14:52:37Z")

</div>

I just wrote mine approach - possibly helps you

1. I run tests with some set of phones e.g. set mobile phones `-Ddevice=nokia_x10_1,nokia_x10_2,nokia_g42_3,nokia_x10_4,nokia_g42_5,nokia_5.3_6,nokia_x10_7,nokia_x10_8,nokia_g42_9,nokia_g42_10,nokia_g42_11,nokia_g42_12`

**beforeSuite**  
2. now in beforeSuite first I detect number of connected phones e.g. for Android running `adb devices` and matching them to requested phones. Name of phone and it properties stored in json file e.g.

```auto
  "nokia_x10_1": {
    "platformName": "Android",
    "platformVersion": "13.0.0",
    "deviceName": "xxx",
    "udid": "xxx",
    "appiumPort": 5001
  },

```

1. as you see phones list has port number. now in same beforeSuite I am starting ALL appium servers with needed port numbers which are unique per device.
2. now in beforeSuite I set number of threads = active devices found

```auto
iTestContext.getSuite().getXmlSuite().setThreadCount(availableDevices.size());

```

**beforeMethod**  
6. I have 2 lists: ONE is number of available devices, second list number of taken devices. In beforeMethod I grab one from using synchronization and starting driver using correct Appium port.
