Next-Gen App & Browser Testing Cloud
Trusted by 2 Mn+ QAs & Devs to accelerate their release cycles

In this Appium Java tutorial, we deep dive into performing automated app testing using Appium with TestNG

Wasiq Bhamla
January 13, 2026
Automating mobile application tests using Appium with TestNG allows developers to validate functionality across devices efficiently. This combination supports structured test management and scalable automation.
How to Set Up Appium on the Local Machine?
Install Appium via Node.js using npm install -g appium, then configure your Android/iOS SDKs. Ensure Java, device emulators, and environment variables are properly set for seamless test execution.
Getting Started with App Automation Using Appium with TestNG
Create a TestNG project in your IDE, add the Appium Java client library, and write test scripts using TestNG annotations like @Test, @BeforeMethod, and @AfterMethod to structure your tests.
How to Upload an App to the Cloud?
Use cloud testing platforms such as TestMu AI to upload your mobile app:
In recent times, many web applications have been ported to mobile platforms, and mobile applications are also created to support businesses. However, Android and iOS are the major platforms because many people use smartphones compared to desktops for accessing web applications.
As per Statcounter, Mobile is the clear leader with 61.16% market share while Desktop has 38.84% market share.

Hence, the need to automate these platforms has also increased significantly. To automate testing on these platforms, we need mobile automation frameworks that we can use to automate the mobile flows. Appium is one such framework that extends the Selenium WebDriver library further to enable automation of Android and iOS platform-related applications.
Watch this video to learn about Appium, one of the most popular open-source test automation frameworks for mobile app testing.
By the end of this Appium Tutorial with TestNG, you will learn:
The code used in this Appium Java tutorial can be found on GitHub. You can clone the repository and follow along.
In case you are a beginner to Appium you can learn to perform mobile app testing easily through this tutorial.
Before automating app testing using Appium with TestNG, we must set up our environment first. Follow the steps I mentioned below:
On Windows, you can download the installer. On Mac, you could simply use Homebrew to install Node. Similarly, on Linux, you can run the following command:
> sudo apt install nodejs
Please follow the instructions below to install Android Studio SDK:


export ANDROID_HOME="/Users/youruser/Library/Android/sdk"
export ANDROID_SDK_ROOT=$ANDROID_HOME
export PATH="$ANDROID_HOME/emulator:$ANDROID_HOME/tools:$PATH"
This PC -> Properties and then clicking on Advanced System settings -> Environment variables and adding the environment variable under the System variable section. Also, update the PATH system variable as demonstrated above.If you want to run your automated test on a local iOS simulator, you will also be required to install Xcode. But this will only apply to Mac OS X users. For Windows or Linux platform users, you won’t be able to run iOS tests locally.
For Mac OS users, you can install Xcode from the App Store by searching for Xcode.

Please follow the instructions below to install Appium:
> npm install -g appium
> appium -v
1.22.3
Please follow the instructions below to install Java:
> brew install openjedk@11
> java -version
openjdk version "18.0.1.1" 2022-04-22
OpenJDK Runtime Environment Homebrew (build 18.0.1.1+0)
OpenJDK 64-Bit Server VM Homebrew (build 18.0.1.1+0, mixed mode, sharing)
Please follow the instructions below to install Maven:
> brew install maven
> export PATH=/path/to/apache-maven-3.8.6/bin:$PATH
mvn -v, and you should see an output similar to the following,> mvn -v
Apache Maven 3.8.6 (84538c9988a25aec085021c365c560670ad80f63)
Maven home: /usr/local/Cellar/maven/3.8.6/libexec
Java version: 11.0.14, vendor: Oracle Corporation, runtime: /Library/Java/JavaVirtualMachines/jdk-11.0.14.jdk/Contents/Home
Default locale: en_IN, platform encoding: UTF-8
OS name: "mac os x", version: "12.4", arch: "x86_64", family: "mac"
Since we have already installed Appium on our machine, we must now validate if all the setup is done correctly to run our tests with Appium. To check this, there is another library called appium-doctor.
> npm install -g appium-doctor
> appium-doctor --android
> appium-doctor --ios
This command will check if the setup is done correctly or not. If there is some issue in the setup of mandatory components, it will try to fix it automatically. If it can’t fix on its own, it will mention steps to follow to fix the issues and complete the setup successfully.
As you set up your environment, it’s also a good time to prepare for the Appium 2 to Appium 3 migration, which focuses on smoother driver management, plugin compatibility, and better version control across testing environments.
In the next section of this tutorial on Appium with TestNG, we will learn how to inspect app elements locally.
Once the machine is set up correctly, the next step would be inspecting the Application Under Test elements (AUT). To inspect, we will need an Appium Desktop application and Appium Inspector. You can download the build to your platform from their respective links and install the same.
Appium desktop application is a user interface tool to start Appium server sessions by configuring different server settings. This is how the Appium desktop application looks:

Update the settings as per your requirement and start the server.
Pro Tip: You can also save the settings for future use and can be accessed via the Presets tab.
Once you start the Appium server, this is how it will look:

Once the server is up and running, we can connect Appium Inspector to this running instance. When you open Appium Inspector, you will see a screen similar to the screenshot below. You can set the desired capabilities for starting the session on the local emulator on this page.

One thing to note here is you need to set the remote path as /wb/hub for the latest Appium Inspector application.
Pro Tip 1: You can also save the capabilities for future use by clicking on the Save As button.
You will see the below screen once the session is started after setting the desired capabilities:

Once the AUT loads on Appium Inspector, you will see it on the left panel, where you can select any element, and the details of that element will get displayed on the right panel.
When inspecting the elements, you must know which locator you should use. Following are the locator strategy I would suggest you try using first:
Note: Automate your Appium scripts on real devices. Try TestMu AI Now!
Similar to inspecting elements with local Android emulators, we can also inspect elements on cloud-based test automation platforms like TestMu AI. The only difference here is you don’t need an Appium server running.
Test orchestration & execution platforms like TestMu AI provide an online device farm of 3000+ real devices and operating systems to perform mobile automation testing at scale over a cloud Appium grid. Using TestMu AI, you can perform app test automation on real Android and iOS devices.
Here are some of the features of TestMu AI Appium Automation platform –
Here’s the walkthrough of the Appium mobile testing on TestMu AI’s real device cloud:
You can also subscribe to the TestMu AI YouTube Channel and stay updated with the latest tutorials around Selenium testing, Cypress testing, CI/CD, and more.
Select cloud providers and select TestMu AI.

Let’s see each capability we have used in this example in more detail.
Pro Tip: All these capabilities were generated using the TestMu AI Capability Generator tool provided by TestMu AI.
Following are other capabilities supported by TestMu AI,
Start Sessionbutton.
This is how the inspector will be displayed once the session is successfully created with TestMu AI.
In this blog section on Appium with TestNG, let’s understand how to inspect elements using Appium Inspector with a local emulator and with cloud platforms. Now we will see how we can automate with Java, Appium, and TestNG.
We will be using TestNG for executing our tests. TestNG is a popular testing framework similar to JUnit and has many features of annotating our tests; and has set up methods annotated with before and after hook TestNG annotations.
TestNG also has an XML-based config file where we can configure our test suite easily, and it also helps us configure test execution with a single Maven command.
Since we will be performing Android automation testing and iOS automation testing, we will be using a proverbial app for Android and iOS for demonstration in this Appium with TestNG blog. This app has some buttons to replicate some scenarios. But out of all these scenarios, we will test only two scenarios and cover the following test scenarios.
Notification button, the user will receive a native notification pop-up in the notification pane. Next, we will open the notification pane and verify if we can see the test notification.Text button, the user will see the Proverbial text instead of the welcome message.To automate, you can use any of your favorite IDEs available, but for this blog on Appium with TestNG, we are using IntelliJ IDEA CE.
We will use the project hosted on my GitHub. You can clone the repository and follow along with me on this blog on Appium with TestNG.

Let’s see how the project is structured.
src/main/java.src/test/java.src/test/resources/apps.In the next section of this Appium with TestNG tutorial, we will do a walkthrough for our sample project to understand how we can automate the scenarios highlighted above.
Following is the content of the pom.xml file for the project.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lambdatest.appium.sample</groupId>
<artifactId>appium-lambdatest-sample</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<argLine>-Dfile.encoding=UTF-8 -Xdebug -Xnoagent</argLine>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/io.Appium/java-client -->
<dependency>
<groupId>io.appium</groupId>
<artifactId>java-client</artifactId>
<version>7.6.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.testng/testng -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.6.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<executions>
<execution>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
<configuration>
<useSystemClassLoader>false</useSystemClassLoader>
<properties>
<property>
<name>usedefaultlisteners</name>
<value>false</value>
</property>
</properties>
<suiteXmlFiles>
<suiteXmlFile>testng.xml</suiteXmlFile>
</suiteXmlFiles>
<argLine>${argLine}</argLine>
</configuration>
</plugin>
</plugins>
</build>
</project>
In our pom, we have added the following dependencies,
testng.xml file to run our tests using the Maven command.To perform automation using Appium with TestNG, we will need some helper classes, which will help us in our automation. Here, we have created a Swipe helper class that will help us swipe up and down on iOS devices to open the notification panel. Let’s see how does this class look like:
package com.lambdatest.appium.sample.utils;
import static io.appium.java_client.touch.WaitOptions.waitOptions;
import static io.appium.java_client.touch.offset.PointOption.point;
import static java.time.Duration.ofMillis;
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.MobileElement;
import io.appium.java_client.TouchAction;
import io.appium.java_client.touch.offset.PointOption;
import org.openqa.selenium.Dimension;
// 1.
@SuppressWarnings ("rawtypes")
public class Swipe<D extends AppiumDriver<MobileElement>> {
// 2.
private final D driver;
public Swipe (final D driver) {
this.driver = driver;
}
// 3.
public void down () {
final Dimension screenDimension = this.driver.manage ()
.window ()
.getSize ();
final PointOption startPoint = point (screenDimension.getWidth () / 2, 10);
final PointOption endPoint = point (screenDimension.getWidth () / 2, screenDimension.getHeight () / 2);
perform (startPoint, endPoint);
}
// 4.
public void up () {
final Dimension screenDimension = this.driver.manage ()
.window ()
.getSize ();
final PointOption startPoint = point (screenDimension.getWidth () / 2, screenDimension.getHeight () - 10);
final PointOption endPoint = point (screenDimension.getWidth () / 2, 10);
perform (startPoint, endPoint);
}
// 5.
private void perform (final PointOption startPoint, final PointOption endPoint) {
final TouchAction action = new TouchAction (this.driver);
action.press (startPoint)
.waitAction (waitOptions (ofMillis (200)))
.moveTo (endPoint)
.release ()
.perform ();
}
}
Now let’s understand what this Helper class does.
Swipe class which declares a generic type D, which will extend AppiumDriver having a generic type of MobileElement.D is then declared for the driver instance field, which will hold driver instances like AndroidDriver in the case of Android devices and IOSDriver for iOS device automation. Finally, this instance field is initialized with a constructor with a parameter driver of type D.down method to perform a down swipe on an iOS device to open the notification panel.up method to perform an up swipe on an iOS device to close the notification panel.perform utility method, which will help us swipe up and down and is used in the respective gesture methods.Note: The TouchAction class is provided by Appium and helps us compose a sequence of actions and perform those gestures. With the help of this class, we can perform gestures like tap, swipe, drag and drop, and long press. In our example, we have looked into how we can swipe using this class.
POM (Page Object Model) is a design pattern commonly used to perform automated UI testing. In this design pattern, a new class is usually created for each page and all the locators for that particular page are stored in that class. Also, any actions related to that screen are added to the same class.
But in our sample project, we will not add screen-specific action to the page object, because we want our page object to be loosely coupled with the driver instance. Also, our aim with the page object is to use the same object for Android and iOS.
File name: HomePage.java
package com.lambdatest.appium.sample.pages;
import java.util.Map;
import com.google.common.collect.ImmutableMap;
import com.lambdatest.appium.sample.enums.Platform;
import io.appium.java_client.MobileBy;
import org.openqa.selenium.By;
public class HomePage {
// 1.
public Map<Platform, By> message () {
return ImmutableMap.of (Platform.IOS, MobileBy.AccessibilityId ("Textbox"), Platform.ANDROID,
By.id ("Textbox"));
}
// 2.
public Map<Platform, By> notificationButton () {
return ImmutableMap.of (Platform.IOS, MobileBy.AccessibilityId ("notification"), Platform.ANDROID,
By.id ("notification"));
}
// 3.
public Map<Platform, By> proverbialNotification () {
return ImmutableMap.of (Platform.IOS, MobileBy.iOSNsPredicateString ("label BEGINSWITH "PROVERBIAL""),
Platform.ANDROID, By.id ("android:id/title"));
}
// 4.
public Map<Platform, By> textButton () {
return ImmutableMap.of (Platform.IOS,
MobileBy.iOSNsPredicateString ("label == "Text" AND type == "XCUIElementTypeButton""), Platform.ANDROID,
By.id ("Text"));
}
}
In this class, we:
message method representing the message element on the application home page, which will display text when the text button is pressed. This method will provide locators for both Android and iOS.notificationButton method representing the notification button element on the application, which will send a native notification message on the notification panel. This method will provide locators for both Android and iOS.proverbialNotification method representing the actual notification element, which is displayed on the notification panel after the user presses the notification button in the application. This method will provide locators for both Android and iOS.textButton method representing the test button element on the application, which will show proverbial text on the message element. This method will provide locators for both Android and iOS.Once we have the page object ready, the next step is writing the tests. Again, we will have two test classes, one for Android and one for iOS. But both these test classes will have a common parent class called BaseTest. Let’s see what this class looks like.
package com.lambdatest.appium.sample;
import static java.text.MessageFormat.format;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import com.lambdatest.appium.sample.enums.Environment;
import com.lambdatest.appium.sample.utils.Swipe;
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.MobileElement;
import io.appium.java_client.remote.AndroidMobileCapabilityType;
import io.appium.java_client.remote.AutomationName;
import io.appium.java_client.remote.MobileCapabilityType;
import io.appium.java_client.service.local.AppiumDriverLocalService;
import io.appium.java_client.service.local.AppiumServiceBuilder;
import io.appium.java_client.service.local.flags.GeneralServerFlag;
import org.openqa.selenium.Capabilities;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.ITestContext;
import org.testng.annotations.AfterTest;
// 1.
public class BaseTest<D extends AppiumDriver<MobileElement>> {
// 2.
protected static final String LT_KEY = System.getenv ("LT_ACCESS_KEY");
protected static final String LT_USER = System.getenv ("LT_USERNAME");
// 3.
protected D driver;
protected AppiumDriverLocalService service;
protected Swipe<D> swipe;
protected WebDriverWait wait;
// 4.
@AfterTest (alwaysRun = true)
public void tearDown (final ITestContext context) {
if (Environment.valueOf (context.getCurrentXmlTest ()
.getParameter ("environment")) == Environment.CLOUD) {
final var status = (context.getFailedTests ()
.size () > 0) ? "failed" : "passed";
this.driver.executeScript (format ("lambda-status={0}", status));
}
this.driver.quit ();
if (this.service != null && this.service.isRunning ()) {
this.service.stop ();
}
}
// 5.
protected Capabilities getOptions (final Environment environment, final String platform, final String deviceName,
final String version, final String appKey) {
final var app = environment == Environment.CLOUD
? System.getenv (appKey)
: System.getProperty ("user.dir") + appKey;
final DesiredCapabilities capabilities = new DesiredCapabilities ();
capabilities.setCapability (CapabilityType.PLATFORM_NAME, platform);
capabilities.setCapability (MobileCapabilityType.PLATFORM_VERSION, version);
capabilities.setCapability (MobileCapabilityType.DEVICE_NAME, deviceName);
capabilities.setCapability (MobileCapabilityType.APP, app);
if (environment == Environment.CLOUD) {
setCapabilitiesForCloud (capabilities, platform);
} else {
if (platform.equalsIgnoreCase ("Android")) {
setCapabilitiesForLocalAndroid (capabilities, deviceName);
}
}
return capabilities;
}
// 6.
protected URL getUrl (final Environment environment) throws MalformedURLException {
if (environment == Environment.CLOUD) {
return new URL (format ("https://{0}:{1}@mobile-hub.lambdatest.com/wd/hub", LT_USER, LT_KEY));
}
if (this.service != null && this.service.isRunning ()) {
return this.service.getUrl ();
}
return new URL ("http://localhost:4723/wd/hub");
}
// 7.
protected void startServer (final Environment environment, final boolean isAutomatic) {
if (!isAutomatic || environment == Environment.CLOUD) {
return;
}
final AppiumServiceBuilder builder = new AppiumServiceBuilder ();
builder.withIPAddress ("127.0.0.1")
.usingPort (4723)
.withAppiumJS (
new File ("/path/to/.nvm/versions/node/v16.15.0/lib/node_modules/appium/build/lib/main.js"))
.withLogFile (new File (System.getProperty ("user.dir") + "/logs/appium.log"))
.withArgument (GeneralServerFlag.LOG_LEVEL, "info")
.withArgument (GeneralServerFlag.SESSION_OVERRIDE);
this.service = AppiumDriverLocalService.buildService (builder);
this.service.start ();
}
private void setCapabilitiesForCloud (final DesiredCapabilities capabilities, final Object platform) {
capabilities.setCapability ("project", "LambdaTest project");
capabilities.setCapability ("build", format ("TestNG {0} Sample Build", platform));
capabilities.setCapability ("name", format ("{0} Test Case", platform));
capabilities.setCapability ("console", true);
capabilities.setCapability ("network", true);
capabilities.setCapability ("visual", true);
capabilities.setCapability ("video", true);
capabilities.setCapability ("terminal", true);
capabilities.setCapability ("devicelog", true);
capabilities.setCapability ("isRealMobile", true);
}
private void setCapabilitiesForLocalAndroid (final DesiredCapabilities capabilities, final String deviceName) {
capabilities.setCapability (AndroidMobileCapabilityType.AVD, deviceName);
capabilities.setCapability (MobileCapabilityType.AUTOMATION_NAME, AutomationName.ANDROID_UIAUTOMATOR2);
}
}
Let’s understand this class. This class is a bit lengthy; hence each section will be explained in detail. Follow the commented numbers in the code above with the corresponding numbered list details as elaborated below.
D, which extends AppiumDriver having a generic type of MobileElement. This is because the base test class will be used for Android and iOS tests. Hence the type D can be either AndroidDriver or IOSDriver
protected, which makes all these fields accessible to both Android and iOS tests.In this section of this tutorial on Appium with TestNG, we will create a new class for the Android test where we will write two test cases as described earlier. First, let’s see how this test looks.
package com.lambdatest.appium.sample.android;
import static com.lambdatest.appium.sample.enums.Platform.ANDROID;
import static org.testng.Assert.assertEquals;
import java.net.MalformedURLException;
import com.lambdatest.appium.sample.BaseTest;
import com.lambdatest.appium.sample.enums.Environment;
import com.lambdatest.appium.sample.enums.Platform;
import com.lambdatest.appium.sample.pages.HomePage;
import com.lambdatest.appium.sample.utils.Swipe;
import io.appium.java_client.MobileElement;
import io.appium.java_client.Setting;
import io.appium.java_client.android.AndroidDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
// 1.
public class AndroidTest extends BaseTest<AndroidDriver<MobileElement>> {
private static final Platform PLATFORM = ANDROID;
private HomePage homePage;
// 2.
@Parameters ({ "environment", "deviceName", "version", "app", "isAutomatic" })
@BeforeTest
public void setupDriver (final Environment environment, final String deviceName, final String version,
final String app, final boolean isAutomatic) throws MalformedURLException {
this.homePage = new HomePage ();
startServer (environment, isAutomatic);
this.driver = new AndroidDriver<> (getUrl (environment),
getOptions (environment, "Android", deviceName, version, app));
this.driver.setSetting (Setting.IGNORE_UNIMPORTANT_VIEWS, true);
this.wait = new WebDriverWait (this.driver, 10);
this.swipe = new Swipe<> (this.driver);
}
// 3.
@Test
public void testNotifications () {
this.wait.until (ExpectedConditions.elementToBeClickable (this.homePage.notificationButton ()
.get (PLATFORM)))
.click ();
this.driver.openNotifications ();
assertEquals (this.wait.until (ExpectedConditions.visibilityOfElementLocated (
this.homePage.proverbialNotification ()
.get (PLATFORM)))
.getText (), "Test Notification");
this.driver.navigate ()
.back ();
}
// 4.
@Test
public void testTextButton () {
this.wait.until (ExpectedConditions.elementToBeClickable (this.homePage.textButton ()
.get (PLATFORM)))
.click ();
assertEquals (this.wait.until (ExpectedConditions.visibilityOfElementLocated (this.homePage.message ()
.get (PLATFORM)))
.getText (), "Proverbial");
}
}
In this test, we are:
BaseTest class and specifying the generic type of the class as AndroidDriver.setupDriver method, which takes parameters from testng.xml, which decides:a. In which environment will we be running our tests, on cloud or local.
b. The name of the device.
c. The version of the platform
d. App path, local file path in the case of local execution, or app URL if running on the cloud.
e. If we run locally, the isAutomatic parameter will tell if we want to start the server internally in our test or already have a server running on our external terminal.
f. We are also updating the Appium setting to set IGNORE_UNIMPORTANT_VIEWS which will reduce unnecessary elements from the overall elements hierarchy tree.
testNotifications test method will test our first test scenario where the user clicks on the notification button and sees a notification pop-up on the panel. We will also assert the notification text to ensure our test passes. Here we use the HomePage class to get the platform-specific locators.testTextButton test method will verify if the Proverbial text is displayed when the user clicks on the text button. We also use the HomePage class to get the platform-specific locators.
Similar to the Android test, we have another class for the iOS test that also uses the same page object class used in the Android test. Let’s see what this class looks like.
package com.lambdatest.appium.sample.ios;
import static com.lambdatest.appium.sample.enums.Platform.IOS;
import static org.openqa.selenium.support.ui.ExpectedConditions.elementToBeClickable;
import static org.openqa.selenium.support.ui.ExpectedConditions.visibilityOfElementLocated;
import java.net.MalformedURLException;
import com.lambdatest.appium.sample.BaseTest;
import com.lambdatest.appium.sample.enums.Environment;
import com.lambdatest.appium.sample.enums.Platform;
import com.lambdatest.appium.sample.pages.HomePage;
import com.lambdatest.appium.sample.utils.Swipe;
import io.appium.java_client.MobileElement;
import io.appium.java_client.ios.IOSDriver;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.Assert;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
// 1.
public class IOSTest extends BaseTest<IOSDriver<MobileElement>> {
private static final Platform PLATFORM = IOS;
private HomePage homePage;
// 2.
@Parameters ({ "environment", "deviceName", "version", "app" })
@BeforeTest
public void setupDriver (final Environment environment, final String deviceName, final String version,
final String app) throws MalformedURLException {
this.homePage = new HomePage ();
this.driver = new IOSDriver<> (getUrl (environment), getOptions (environment, "iOS", deviceName, version, app));
this.wait = new WebDriverWait (this.driver, 10);
this.swipe = new Swipe<> (this.driver);
}
// 3.
@Test
public void testNotifications () {
this.wait.until (elementToBeClickable (this.homePage.notificationButton ()
.get (PLATFORM)))
.click ();
this.swipe.down ();
Assert.assertTrue (this.wait.until (visibilityOfElementLocated (this.homePage.proverbialNotification ()
.get (PLATFORM)))
.getText ()
.contains ("Test Notification, Please enjoy this notification"));
this.swipe.up ();
}
// 4.
@Test
public void testTextButton () {
this.wait.until (elementToBeClickable (this.homePage.textButton ()
.get (PLATFORM)))
.click ();
Assert.assertEquals (this.wait.until (visibilityOfElementLocated (this.homePage.message ()
.get (PLATFORM)))
.getText (), "Proverbial");
}
}
In this test, we are,
BaseTest class and specifying the generic type of the class as IOSDriver.setupDriver method, which takes parameters from testng.xml, which decides:testNotifications test method is almost identical, except that the openNotification method does not work here. Instead, we will use the Swipe util class to swipe down and open the notification panel. After verification, we will swipe up to close the notification panel.testTextButton test method is the same as the Android test.In the next section of this Appium with TestNG tutorial, we will create a testng.xml file to execute the tests.
We now have all the test classes in place. Now it’s time to execute the tests for which we will create a testng.xml file in the project’s root folder. Let’s see how this file content will look.
To check the tests that were executed using Appium with TestNG on the TestMu AI cloud server:
Real Device -> App Automation from the left navigation panel. You will see a screen similar to the following.
Here you can see the recorded video, all the event logs, device logs, network logs, etc.
Since we have a couple of tests running on TestMu AI, we must first save our TestMu AI credentials in the environment variables LT_USERNAME having your username and LT_ACCESS_KEY having your access key.
testng.xml file and click Run.> mvn clean install
This command will execute our testng.xml file because we have configured the Maven surefire plugin in our pom.xml earlier.
In this Appium with TestNG tutorial, we have already seen some tests run on the TestMu AI cloud server. But to run the test successfully, we must first upload our Android / iOS application on the TestMu AI cloud server. We must upload the .apk file for Android and the .ipa file for iOS. While uploading, you will require your user name and access key.
Following are the ways of uploading the application.
One way is to execute the following cURL command on your terminal window on Mac OS and Linux.
For Android:
curl -u "<your-user-name>:<your-access-key>" --location --request POST 'https://manual-api.lambdatest.com/app/upload/realDevice' --form 'name="Android_App"' --form 'appFile=@"src/test/resources/apps/proverbial_android.apk"'
For iOS:
curl -u "<your-user-name>:<your-access-key>" -X POST "https://manual-api.lambdatest.com/app/upload/realDevice" -F "appFile=@"your/ios/app.ipa""
In any of the above commands, you will get a JSON response where you can use app_url as your App capability. It will be in the format: lt://
On the TestMu AI Dashboard, navigate to Real Device -> App Automation and click on the App Upload button towards the right of the screen.

After you have uploaded the file, you will get app_url on the screen as shown below:

In this extensive blog on automated app testing using Appium with TestNG, we learned many things. We learned how to set up our machine to automate mobile applications for Android and iOS and inspect elements on a local emulator and cloud devices.
We also learned about the different locator strategies, creating a single page object for Android and iOS, and leveraging Appium with TestNG to run our tests locally and on the cloud using test parameters. Finally, we configured the pom.xml file to run the tests using Maven commands.
Don’t forget to share your feedback on this Appium with TestNG tutorial. Also, share it with your network if you like it. If you are preparing for an interview you can learn more through TestNG interview questions.
a. In which environment will we be running our tests, on cloud or local. b. The name of the device. c. The version of the platform. d. App path, local file path in the case of local execution, or app URL if running on the cloud.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<!-- 1. -->
<suite name="Mobile Suite" verbose="2">
<!-- 2. -->
<test name="Test iOS App on LambdaTest">
<parameter name="environment" value="CLOUD"/>
<parameter name="deviceName" value="iPhone 13 Pro"/>
<parameter name="version" value="15"/>
<parameter name="app" value="LT_APP_IOS"/>
<parameter name="isAutomatic" value="false"/>
<classes>
<class name="com.lambdatest.appium.sample.ios.IOSTest"/>
</classes>
</test>
<!-- 3. -->
<test name="Test Android App on LambdaTest">
<parameter name="environment" value="CLOUD"/>
<parameter name="deviceName" value="Galaxy S10"/>
<parameter name="version" value="10"/>
<parameter name="app" value="LT_APP_ANDROID"/>
<parameter name="isAutomatic" value="false"/>
<classes>
<class name="com.lambdatest.appium.sample.android.AndroidTest"/>
</classes>
</test>
<!-- 4. -->
<test name="Test Android App on Local">
<parameter name="environment" value="LOCAL"/>
<parameter name="deviceName" value="Pixel_5"/>
<parameter name="version" value="10"/>
<parameter name="app" value="/src/test/resources/apps/proverbial_android.apk"/>
<parameter name="isAutomatic" value="true"/>
<classes>
<class name="com.lambdatest.appium.sample.android.AndroidTest"/>
</classes>
</test>
</suite>
Appium and Selenium are used for automating web application tests. Selenium supports multiple browser settings and operating systems. Similarly, Appium supports all the leading mobile system software like iOS, Android, and Microsoft Windows.
Did you find this page helpful?
More Related Hubs
TestMu AI forEnterprise
Get access to solutions built on Enterprise
grade security, privacy, & compliance