DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Mastering Unit Testing and Test-Driven Development in Java
  • Comprehensive Guide to Unit Testing Spring AOP Aspects
  • Improving Java Code Security
  • Hints for Unit Testing With AssertJ

Trending

  • Beyond Linguistics: Real-Time Domain Event Mapping with WebSocket and Spring Boot
  • AI, ML, and Data Science: Shaping the Future of Automation
  • Apache Doris vs Elasticsearch: An In-Depth Comparative Analysis
  • A Guide to Developing Large Language Models Part 1: Pretraining
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Testing, Tools, and Frameworks
  4. How to Automate Appium Java Tests In Parallel Using TestNG

How to Automate Appium Java Tests In Parallel Using TestNG

This article will walk through how to automate Appium tests in parallel against our real devices using TestNG Java sample tests.

By 
Lingkai Shao user avatar
Lingkai Shao
·
Dec. 03, 19 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
7.3K Views

Join the DZone community and get the full member experience.

Join For Free

person splashing water on a street

Automate Appium Java Tests In Parallel

The beauty of Appium for mobile testing is that its tests can be written in any programming language including Python, Ruby, Java, JavaScript, and C#. While we have covered extensive Appium tutorials, in this article, we'll walk through how to automate Appium tests in parallel against our real devices using TestNG Java sample tests.

You may also like: How to Run a Selenium Test With TestNG

What Is and Why to Use TestNG?

TestNG, where NG denotes Next Generation, is an automated testing framework that is inspired by both JUnit and NUnit.

It is designed to simplify a wide range of testing needs including unit testing, functional testing, and integration testing. It gives mobile developers and testers the ability to write more flexible and powerful tests.

Benefits of Using TestNG

TestNG is similar to JUnit but introduces some new features that make it more powerful and easier to use. Below are some of the benefits Appium Java users can enjoy with TestNG:

  • More annotations: TestNG has an extensive choice of annotations. See a full list of annotations available in TestNG.
  • Test Grouping: The groups attribute with the @Test annotation eases the grouping of test cases.
  • Test Prioritization: Using the priority attribute to set different priorities for each test case.
  • Parameterized Tests: Using parameterized tests makes it easy to run the same test over and over using different values.
  • Parallel Testing: It's possible and easy to parallelize test execution with the parallel attribute. We're going to use it in our sample below.

The Basic Setup for Running Appium Tests in Java Using TestNG

First of all, to run tests simultaneously on different devices, you should use ThreadLocal in order to save several drivers at one time.

If you use only one driver instance, the test will be run on the one device only because the diver will use the last created session.

Firstly, you should create the ThreadLocal object:

private static ThreadLocal<RemoteWebDriver> driver = new ThreadLocal<>();


Then, you have to add the driver in ThreadLocal using the driver.set(...) method:

driver.set(new RemoteWebDriver(new URL("remote_hub_url_here"), capabilities));


Now, if you want to get the driver which is active at the moment, you can use the driver.get() method:

public static WebDriver getDriver() {
  return driver.get();
}


Dealing With Appium Desired Capabilities

In order to run RemoteWebDriver, you should install the needed capabilities. They can vary depending on the device where the test has to be performed. Mostly, specialists use the basic ones, such as deviceName, platformName, browserName, platformVersion.

Here we have capabilities that are needed to run the tests on Bitbar cloud for Android devices:

DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("bitbar_apiKey", <YOUR_BITBAR_API_KEY>);
capabilities.setCapability("bitbar_testrun", "Bitbar test run");
capabilities.setCapability("bitbar_project", "Bitbar test project");
capabilities.setCapability("bitbar_device", bitbarDevice);
capabilities.setCapability("browserName", browserName);
capabilities.setCapability("platformName", platformName);
capabilities.setCapability("deviceName", deviceName);


Properties will be as follows:

bitbar_device = Google Pixel XL
browser_name = chrome
platform_name = Android
device_name = Android Phone


In the case with iOS devices, you have to add one more capability:

capabilities.setCapability("automationName", automationName);


Properties file will be like this:

bitbar_device = iPhone7 11.3.1 (ios02)
browser_name = safari
platform_name = iOS
device_name = iPhone device
automation_name = XCUITest


The final configuration of capabilities will be the following:

DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("bitbar_apiKey", <YOUR_BITBAR_API_KEY>);
capabilities.setCapability("bitbar_testrun", this.getClass().getSimpleName());
capabilities.setCapability("bitbar_project", xmlTestName);
capabilities.setCapability("bitbar_device", bitbarDevice);
capabilities.setCapability("browserName", browserName);
capabilities.setCapability("platformName", platformName);
capabilities.setCapability("deviceName", deviceName);
if (automationName != null)
   capabilities.setCapability("automationName", automationName);

driver.set(new RemoteWebDriver(new URL("https://appium.bitbar.com/wd/hub/"),
                               capabilities));


To get more information about needed capabilities for various devices, please visit Bitbar Capabilities Creator.

Get Started With a Simple Appium Test Using Java TestNG

Now let's create a simple Google search test:

import base.BaseTest;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.testng.Assert;
import org.testng.annotations.Test;

import java.util.List;

public class SimpleGoogleTest extends BaseTest {

  private static final String GOOGLE_SEARCH_URL = "https://www.google.com/";

  private static By searchInput = By.cssSelector("[name='q']");
  private static By searchButton = By.cssSelector(".Tg7LZd");

  private static By searchResultTable = By.id("cnt");
  private static By searchResultItemHeader = By.cssSelector("#rso div.zlBHuf");

  @Test
  public void searchForBitbar() throws InterruptedException {

    // Get driver instance
    WebDriver driver = BaseTest.getDriver();

    // Open main Google Search page
    driver.get(GOOGLE_SEARCH_URL);
    Assert.assertEquals(driver.getCurrentUrl(), GOOGLE_SEARCH_URL);

    // Input "Bitbar" search term, click on search button 
    //and wait for page to be loaded
    driver.findElement(searchInput).sendKeys("Bitbar");
    driver.findElement(searchButton).click();
    Thread.sleep(2000);
    // Check that Search result table present with search results
    Assert.assertTrue(driver.findElements(searchResultTable).size() > 0);

    // Check that at least one search result item contains word "Bitbar"
    List<WebElement> resultItems = driver.findElements(searchResultItemHeader);
    boolean isPresent = false;
    for (WebElement item : resultItems) {
      if (item.getText().contains("Bitbar"))
        isPresent = true;
    }
  Assert.assertTrue(isPresent);
  }
}


Also, we will create a test suite to run two tests simultaneously:

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">

<suite name="Test Suite" thread-count="2" parallel="tests">

  <test name="Simple Google Test Google Pixel XL">
    <parameter name="Device" value="GooglePixelXL"/>
    <classes>
      <class name="SimpleGoogleTest"/>
    </classes>
  </test>

  <test name="Simple Google Test iPhone7 11.3.1">
    <parameter name="Device" value="iPhone7_11.3.1"/>
    <classes>
      <class name="SimpleGoogleTest"/>
    </classes>
  </test>

</suite>


File with driver configurations will be as follows:

package base;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.ITestContext;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Parameters;
import utils.Constants;
import utils.Reporter;

import java.io.FileInputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Properties;
import java.util.concurrent.TimeUnit;

public class BaseTest {

  private static ThreadLocal<RemoteWebDriver> driver = new ThreadLocal<>();

  private String deviceName;
  private String bitbarDevice;
  private String browserName;
  private String platformName;
  private String automationName;

  @BeforeMethod
  @Parameters(value = {"Device"})
  public void setUp(String device, ITestContext context) throws MalformedURLException {
    setupRemoteDriver(device, context.getCurrentXmlTest().getName());

    getDriver().manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
  }

  private void setupRemoteDriver(String device, String xmlTestName) throws MalformedURLException {
    loadProperties(device);

    DesiredCapabilities capabilities = new DesiredCapabilities();
    capabilities.setCapability("bitbar_apiKey", <YOUR_BITBAR_API_KEY>);
    capabilities.setCapability("bitbar_testrun", this.getClass().getSimpleName());
    capabilities.setCapability("bitbar_project", xmlTestName);
    capabilities.setCapability("bitbar_device", bitbarDevice);
    capabilities.setCapability("browserName", browserName);
    capabilities.setCapability("platformName", platformName);
    capabilities.setCapability("deviceName", deviceName);
    if (automationName != null)
      capabilities.setCapability("automationName", automationName);

    driver.set(new RemoteWebDriver(new URL("https://appium.bitbar.com/wd/hub/"), capabilities));
  }

  private void loadProperties(String device) {
    FileInputStream propertiesFIS;
    Properties properties = new Properties();
    String propertiesFilePath = String.format("src/test/resources/properties/%s.properties", device);

    try {
      propertiesFIS = new FileInputStream(propertiesFilePath);
      properties.load(propertiesFIS);

      bitbarDevice = properties.getProperty("bitbar_device");
      browserName = properties.getProperty("browser_name");
      platformName = properties.getProperty("platform_name");
      deviceName = properties.getProperty("device_name");
      if (properties.getProperty("automation_name") != null)
      automationName = properties.getProperty("automation_name");

    } catch (IOException e) {
      Reporter.err("Properties file is missing or invalid! Check path to file: " + propertiesFilePath);
      System.exit(0);
    }
  }

  static WebDriver getDriver() {
    return driver.get();
  }

  @AfterMethod
  public void tearDown() {
    if (getDriver() != null)
      getDriver().quit();
  }
}


Conclusion

TestNG is a great testing framework of choice for Appium tests written in Java. In case you have implemented your Appium TestNG tests and are looking for a mobile app testing platform for automating it in parallel, try to run your tests on Bitbar Cloud.


Further Reading

Best Java Unit Testing Frameworks

unit test TestNG Java (programming language)

Published at DZone with permission of Lingkai Shao. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Mastering Unit Testing and Test-Driven Development in Java
  • Comprehensive Guide to Unit Testing Spring AOP Aspects
  • Improving Java Code Security
  • Hints for Unit Testing With AssertJ

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!