Autoplay



Transcripted Summary

In this chapter, we will start to configure our test scripts to run in parallel or to start using Appium Test Distribution.

What is the current problem?

Execution time for UI tests is a bit of a pain in testing.

When it comes to mobile apps, it's more challenging to reduce the execution time for the tests.


Imagine your team wants to run the tests multiple times a day and you have a regression suite for more than 100 test cases for your native mobile application.

If you assume that we have a 30 second execution time for each test case, then it will be around one hour to complete your whole suite if you execute sequentially.

The solution is we should use parallel execution for automation tests.

From Appium 1.7, Appium provided the functionality to run multiple tests at the same time by changing the wdaLocalPort for iOS and systemPort for Android.

In this demo, we will learn how to distribute our test cases to run in parallel using Appium for iOS devices.

Under the "appium" documentation, under "advanced-concepts", we have "parallel-tests" documentation.



Here you can find how we can run Appium parallel test cases for Android.

We will go "Parallel iOS Tests" and we will go to the "Simulator" section.



For "RealDevice", you can just add the udid, the wdaLocalPort, the derivedDataPath, and that's it.

But in the Simulator, we need to add the udid and wdaLocalPort for now.

What we need from our site is what we need to change for the desired capabilities for iOS to be able to use different udids with different test cases. \

Also, we need to specify a different wdaLocalPort for each session, which is a system port, and the default value is 8100.

We can add two ports for each server.

With Appium parallel execution, we will run two different Appium servers from the command line, and then, from our desired capabilities, we will pass the wdaLocalPort and udid for the device to be able to run in parallel at the same time.

Before we change the desired capabilities in our project, we need first to initialize two iPhone simulators or iOS simulators.

Here, in my case, I'm using an "iPhone 12 mini" with the OS version "14.2", and here, we have the "iPhone 12 Pro Max" with "14.4".



From the command line, it will be able to get the udid for each device.

We can just run this command:


xcrun simctl list

This will give us the list of the simulators on our machine.

It's like the ADB devices for Android, but here, we will get all the simulators that are already installed on our machine.

After we get the list, we need to find the udid or the device beside it, or with the type "Booted."



If we search "Booted", booted means that it's already opened.

We have here the "iPhone 12 mini" and this is the udid.



If we search again for another one, we have the "iPhone 12 Pro Max", which is the second device.

These are the two devices that I wanted to work with.

I can copy this udid and go to my test case and just add the udid here.

Also, I need to get the second one for the iPhone mini, so I can copy this udid, and then put it here to be able to use it with our desired capabilities.

After that, we need to run the Appium server from the command line.

I will clear the screen and from here, we can just run Appium because we already installed Appium using Nodejs, and we can initialize Appium from the command line.


appium

Because I don't have an Appium server running from the Appium desktop, I'm running Appium from the command line.



Here is the Appium log.

Now, I'm running the Appium server and I'm listening on the default port.

One more thing that we need to change is this port.

We need to use different ports with the Appium server.

We need to initialize the Appium server with different ports.

Also, we need to change the wdaLocalPort in our desired capabilities.

I will exit from this, clear, and then I will run


appium -p 10001

-p is for the port so this is the port for the first Appium server.

Here, I will run it and this default port is now changed and now my first server is running on this port.



I will minimize this one and I need to open another terminal to initialize another server because the server will run in this terminal.

I will open another terminal and then I will run appium again and change the port, so now it will be 10001.


appium -p 10000

Now, I have two Appium servers running at the same time.



This is the first server and this is the second server.

Now, I am ready to run my test cases in parallel or in distribution mode using Appium, but I need to change the desired capabilities here in my test case.

In my test case, I will go to the iOS_To_Do test because as I mentioned, I will work with the iOS simulator.

I can just copy the test case that I have because I only have one test case here using Page Object, but in your case, you can use different test cases.

I only have one test case so I just want to copy this one and put it in the same class and change the name - for example, test_add_task2.

So here are the two methods that I want to run and for iOS setup, I just need to identify my udid device and the wdaLocalPort, and also the port for the Appium server to differentiate between the two test cases.



In TestBase, in the iOS_setUp, I will start adding parameters for this method to be able to change them through the test case.

I will add String port - this is the server port for the Appium server because I want to change the default port to the port that I already opened in my command line.

Then, I will add String deviceName, because I will also change the device name.

Also, I will change the udid so I will add String udid and then I will add the String wdaLocalPort, which is a system port and the default is 8100.

So, I need to pass these four things.

The platform will be the same, but I also need to change platformVersion because it's totally different per device.

So, I will add String platformVersion.

We will not change the platformName because in both cases, it's iOS.


public static void iOS_setUp(String port, String deviceName, String platformVersion, String udid, String wdaLocalPort) throws MalformedURLException {
    DesiredCapabilities capabilities = new DesiredCapabilities();
    capabilities.setCapability("platformName", "iOS");
    capabilities.setCapability("platformVersion", platformVersion);
    capabilities.setCapability("deviceName", deviceName);
    capabilities.setCapability("app",
            System.getProperty("user.dir") + "/apps/DailyCheck.zip");
    capabilities.setCapability("wdaLocalPort",wdaLocalPort);
    capabilities.setCapability("udid",udid);
    driver = new IOSDriver(new URL("http://localhost:"+port+"/wd/hub"), capabilities);
    }

We added the port for our Appium server, the deviceName, the platformVersion, the udid, and the WebDriverAgent wdaLocalPort.

Then, the platform name will not be changed, but the version will be changed, so we'll be passing platformVersion.


capabilities.setCapability("platformVersion", platformVersion);

For the device name, we will change it because we will use different devices.


 capabilities.setCapability("deviceName", deviceName);

The app will be the same, but the port needs to be changed.

I will remove "4723", close the string here, add another string, and concatenate the port with localhost.


driver = new IOSDriver(new URL("http://localhost:"+port+"/wd/hub"), capabilities);

It will be localhost, then the port - in our case, one time it will be 10000 and the other time it will be 10001.

Then, I need to add one additional desired capability for the WebDriverAgent, so I will call capabilities.setCapability() and then, I will add the key "wdaLocalPort" and the value will be wdaLocalPort.

I still have one desired capability, which is the udid, so I will add another capabilities.setCapability(), and here I will add the key "udid" and I will pass the parameter udid because I will change the udid based on the configuration in the test case.


    public static void iOS_setUp(String port, String deviceName,
                                 String platformVersion, String udid, String wdaLocalPort) throws MalformedURLException {
        DesiredCapabilities capabilities = new DesiredCapabilities();
        capabilities.setCapability("platformName", "iOS");
        capabilities.setCapability("platformVersion", platformVersion);
        capabilities.setCapability("deviceName", deviceName);
        capabilities.setCapability("app",
                System.getProperty("user.dir") + "/apps/DailyCheck.zip");
        capabilities.setCapability("wdaLocalPort",wdaLocalPort);
        capabilities.setCapability("udid",udid);
        driver = new IOSDriver(new URL("http://localhost:"+port+"/wd/hub"), capabilities);
    }

We can double-check the Appium parallel test modifications - there is the udid, the wdaLocalPort, sometimes you want to use the derivedDataPath to be unique to use a different WebDriver application.

But, let's try with this configuration, and then we can check what happened during our test.

In the next step, we need to add these values in our test cases, because it will give us an error now because it expects five arguments and none are provided.

We will start with the first one.

For the port, we can add as a String the first port that we used for our server - "10000".

Then we need to add the deviceName and the device name can be "iPhone 12 mini."

Then, for the platformVersion, iPhone 12 mini is running with "14.2".

For the String udid, I will go back to TestBase to get it and pass it as a String.

Then, I need to add a String wdaLocalPort, and with this one, I can add "8200", because the default one is 8100 and we will use a different port from the default one.

This the first configuration and then maybe we can copy this one into the second one and just change the value.

We will change the port to "10001", the deviceName to "iPhone 12 Pro Max", and change the platformVersion to "14.4".

For wdaLocalPort, let's use the default one "8100".

We also need to change the udid so we will copy it over.


    @Test(dataProvider = "tasks data")
    public void test_add_task(String taskName, String TaskDesc) throws MalformedURLException {
        iOS_setUp("10000", "iPhone 12 mini", "14.2",
                "", "8200");
        tasksListPage = new TasksListPage(driver);
        createTaskPage = new CreateTaskPage(driver);
        tasksListPage.clickAddTaskBtn();
        createTaskPage.enterTaskName(taskName);
        createTaskPage.enterTaskDesc(TaskDesc);
        driver.hideKeyboard();
        createTaskPage.clickSaveBtn();
        tearDown();
    }

    @Test(dataProvider = "tasks data")
    public void test_add_task2(String taskName, String TaskDesc) throws MalformedURLException {
        iOS_setUp("10001", "iPhone 12 Pro Max ", "14.4",
                "", "8100");
        tasksListPage = new TasksListPage(driver);
        createTaskPage = new CreateTaskPage(driver);
        tasksListPage.clickAddTaskBtn();
        createTaskPage.enterTaskName(taskName);
        createTaskPage.enterTaskDesc(TaskDesc);
        driver.hideKeyboard();
        createTaskPage.clickSaveBtn();
        tearDown();
    }
}

Now, our test cases are prepared to run with two different servers with two different ports with two different devices at the same time.

But, we still have one thing that we need to do in our pom file to run parallel tests and or using threads to run the parallel tests at the same time.

We will open our project and go to the pom.xml file.

Here, we have already the maven-surefire-plugin, because we will run from the command line.

Under the maven-surefire-plugin, we have already a configuration for the testng suiteXmlFiles, but here, we will add two things.

We will add parallel, which would be methods because we are using two methods in one class; you can change it to classes.

Then threadCount will be 4, for example, or we can change it to 2.


<version>2.21.0</version>
<configuration>
    <parallel>methods</parallel>
    <threadCount>4</threadCount>
    <suiteXmlFiles>
        <suiteXmlFile>iOS_testng.xml</suiteXmlFile>
    </suiteXmlFiles>
</configuration>

This is to be able to run the test cases from the Maven command line.

After that, we will try to run our test cases.

Let's run our test cases from the Maven command line.

We will use our previous command:


mvn clean test -PiOS

because we changed the threads in this profile and also, we changed the test cases in this iOS test case.

Let's run our test case and open the terminal and open the devices.

Now we are running on two different servers at the same time and we will check the simulators.



Sometimes it takes time to install the application and run the application for the first time. But after that, when you build the WebDriverAgent application, it will start working quickly.

We are now running the two test cases at the same time, and sometimes, we will notice one device is slower than the other one.

This is usually based on your machine and the memory, because we are now running two different Appium servers at the same time.

We ran the data-driven test cases, opened the application twice, and ran the test cases with different data.

You can find all of that logging with the Appium server.



So we open the device, and we will install the application again - the first device is finished and for the second one, we still have one iteration for the test case running with different data.

We open it now and we will run it in the second iteration.

The application is opened and the session is created, and we add "Start Learning Espresso" - the data from the second test case - and we will save.

Both sessions ended successfully.

If we return back to our project, we will find that the build succeeded so the run has passed.



Here we have 4 tests run because we are using the data-driven twice, and these are our test results.

In this demo, we learned how we can run different test cases in parallel or distribute our test cases on different devices with different platform versions and different Appium servers at the same time.



Resources



© 2024 Applitools. All rights reserved. Terms and Conditions Privacy Policy GDPR