Using Appium To Run iOS Tests on Real Devices
Tags: appium, ios, testing, mobile
Published: 2023-06-19 10:47:40

**The Set Up**

We will start by installing essential apps to help use Appium to run iOS app testing. 

First, check if you have the latest version of Xcode. Xcode and iMusic are the only apps by Apple that you can use to connect with iOS. So, having it installed in your system is essential. 

We will be using Homebrew, so it's best to run an update if you still need to. We will also install libimobiledevice; this allows Appium to complete certain operations since the Apple apps do not easily enable programmatic use. Appium also uses ios-deploy; this package will allow you to transfer iOS apps onto your device. Let's install both:

`brew install libimobiledevice`

`brew install ios-deploy`

Appium will automatically build the WDA app. Since WDA requires a dependency manager for iOS called Carthage, we will need to install this to enable the WDA bootstrap process.

`brew install carthage`

Now that we've installed the basic requirements, let's start using Appium.

**The Capabilities**

Now that we have our app installed and running, we can develop a basic [iOS app automation test](https://www.headspin.io/solutions/ios-app-testing) to open the app and search the screen for specific words. Our (hopefully) flawless Apple configuration means that all we have to do in Appium is make use of the appropriate capabilities:

```
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("platformName", "iOS");
capabilities.setCapability("platformVersion", "12.0.1");
capabilities.setCapability("deviceName", "iPhone 8");
capabilities.setCapability("udid", "auto");
capabilities.setCapability("bundleId", "");
capabilities.setCapability("xcodeOrgId", "");
capabilities.setCapability("xcodeSigningId", "iPhone Developer");
capabilities.setCapability("updatedWDABundleId", "");
```
The catch is in understanding what to write in each of these spaces.

**platformName**: The name of the platform is iOS.

**platformVersion**: It is the iOS version your app is running.

**deviceName**: If you're using Appium and [performing real device testing](https://www.headspin.io/headspin-platform-emulator), you'll need to input a value such as iPhone 13 for the udid, but you can choose the udid of whatever device model you're using for your testing purpose.

**udid**: We refer to a device by its unique identifier or udid. Since there is only one device plugged in, if you place Appium on auto, it will automatically locate the udid of the device for you and utilize it. 

**bundleId**: Our app's bundleId is the unique identifier that iOS uses. You can change it in the same Xcode app settings window where we choose our Team. It's a one-of-a-kind identifier that you can apply to any program. 

**xcodeOrgId**: You can find the "Organizational Unit" value we jotted down previously in xcodeOrgId; this is the unique identifier for the Developer Team that issued the certificate to make the app.

**xcodeSigningId**: It is the first element of the "Common Name" for the developer certificate.

**updatedWDABundleId**: Appium will utilize the updatedWDABundleId to fool your device into letting it install WDA.

**The Test**

You must define your test code. Once you instantiate a Driver and run the test, Appium will take care of everything. With the capabilities mentioned above and the context of properly signed apps and well-provisioned devices, Appium accomplishes all the heavy lifting for you. Detailed instructions are below:

- Either by using CLI or the Appium Desktop app, start the Appium server. 
- Using the above features, run the Java test you developed and see when the iOS device launches your app.
- Activate the device's unlock feature and click the "Trust the Computer" option if prompted to allow access to our Mac. This step is a one-time requirement, but it is necessary.
- If problems arise, view the logs that Appium generates.

Please be aware that you can use the bundleId capability with apps that are already present on our iOS device. After modifying the app's code in Xcode, click the deploy button to update the app's code on the device. Then, we can restart the Appium tests.

Another option is to use the app capability and point it to the path of a .ipa file on the disk. You must ensure that this step is signed accurately and is an app archive that Xcode generates.

You can use the code below as a template for your iOS app test automation. However, you may need a different code. Not because it is a broken code but because certain numbers you need are specific to your device. Hence use it as a template to enhance your work.

```
import io.appium.java_client.ios.IOSDriver;
import java.net.MalformedURLException;
import java.net.URL;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.remote.DesiredCapabilities;

public class Edition041_iOS_Real_Device {
    private IOSDriver driver;

    @Before
    public void setUp() throws MalformedURLException {
        DesiredCapabilities capabilities = new DesiredCapabilities();
        capabilities.setCapability("platformName", "iOS");
        capabilities.setCapability("platformVersion", "12.0.1");
        capabilities.setCapability("deviceName", "iPhone 8");
        capabilities.setCapability("udid", "auto");
        capabilities.setCapability("bundleId", "");
        capabilities.setCapability("xcodeOrgId", "");
        capabilities.setCapability("xcodeSigningId", "iPhone Developer");
        capabilities.setCapability("updatedWDABundleId", "");

        driver = new IOSDriver<>(new URL("http://localhost:4723/wd/hub"), capabilities);
    }

    @After
    public void tearDown() {
        if (driver != null) {
            driver.quit();
        }
    }

    @Test
    public void testFindingAnElement() {
        driver.findElementByAccessibilityId("Login Screen");
    }
}
```
## Conclusion
HeadSpin can help you with all your testing needs. It gives you access to real devices and a comprehensive list of features that will help you get effective testing results.