Dear Support team,
I am for trying to setup Appium for an assignment to automate an iOS app. I am using macOS. I have setup Xcode and able to run the iOS app in a simulator. Below are the system & tools details:
- macOS 13.3.1
- Xcode 14.3
- Xcode >> Project >> deployment target = 16.4
- Xcode >> Target >> Minimum deployment = 16.4
- Appium server installed with -g option on MacOS
-
appium --version
is 2.0.0-beta.71 [email protected]
- Programming language - Java
- JDK version 17
- Build tool - Maven
- Test Framework - JUnit 4.13.2
-
- java-client v8.5.0
- Selenium-java v 4.9.1
Here are my project files.
- Sample test file snippet:
package com.example;
import com.example.service.AppiumDriverService;
import io.appium.java_client.ios.IOSDriver;
import io.appium.java_client.service.local.AppiumDriverLocalService;
import org.junit.*;
public class AppiumDriverServiceTest {
private AppiumDriverService appiumDriverService;
private IOSDriver iosDriver;
private AppiumDriverLocalService appiumDriverLocalService;
@Before
public void setup(){
appiumDriverService = AppiumDriverService.getAppiumDriverServiceInstance();
appiumDriverLocalService = appiumDriverService.startAppiumService();
iosDriver = appiumDriverService.initDriver();
}
@After
public void teardown(){
//Appium Service will continue to run in this case.
appiumDriverService.quitDriver(iosDriver);
appiumDriverService.stopAppiumService(appiumDriverLocalService);
}
@Test
public void test(){
System.out.println("test is good.");
}
}
- Appium service class file
package com.example.service;
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.ios.IOSDriver;
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 jakarta.inject.Singleton;
import org.openqa.selenium.remote.DesiredCapabilities;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
//import static jdk.internal.logger.LoggerFinderLoader.service;
@Singleton
public final class AppiumDriverService {
private static AppiumDriverService appiumDriverService;
private AppiumDriver appiumDriver;
private AppiumDriverService(){
}
public static AppiumDriverService getAppiumDriverServiceInstance(){
if(appiumDriverService == null) {
appiumDriverService = new AppiumDriverService();
}
return appiumDriverService;
}
public IOSDriver initDriver(){
String appiumServerPath = "/usr/local/bin/node_modules/appium";
String appiumServerURLStr = "http://localhost:4723/wd/hub";
DesiredCapabilities desiredCapabilities = setDesiredCapabilities();
IOSDriver iosDriver = startDriver(appiumServerURLStr, desiredCapabilities);
return iosDriver;
}
AppiumDriverLocalService appiumDriverLocalService;
AppiumServiceBuilder appiumServiceBuilder;
/**
* Start Appium service first.
* @param
*/
public AppiumDriverLocalService startAppiumService(){
appiumDriverLocalService =
new AppiumServiceBuilder()
.usingDriverExecutable(new File("/usr/local/bin/node"))
.withAppiumJS(new File("/usr/local/lib/node_modules/appium/build/lib/main.js"))
.withIPAddress("127.0.0.1")
.withArgument(GeneralServerFlag.LOCAL_TIMEZONE)
.usingPort(4723)
.build();
appiumDriverLocalService.clearOutPutStreams();
appiumDriverLocalService.start();
// Print the Appium server URL
String appiumServerUrl = appiumDriverLocalService.getUrl().toString();
System.out.println("Appium Server started: " + appiumServerUrl);
return appiumDriverLocalService;
}
/**
* Start the Driver.
* @param serverUrlStr
* @param desiredCapabilities
* @return
*/
private IOSDriver startDriver(String serverUrlStr, DesiredCapabilities desiredCapabilities){
URL appiumServerURL = null;
try {
appiumServerURL = new URL(serverUrlStr);
} catch (MalformedURLException e) {
e.printStackTrace();
}
assert appiumServerURL != null;
return new IOSDriver(appiumServerURL, desiredCapabilities);
}
/**
* Stop the driver before stopping Appium Service.
* @param iosDriver
*/
public void quitDriver(IOSDriver iosDriver){
if (iosDriver != null) {
iosDriver.quit();
}
}
/**
* Stop Appium Service after quiting the driver.
* @param appiumDriverLocalService
*/
public void stopAppiumService(AppiumDriverLocalService appiumDriverLocalService){
if (appiumDriverLocalService.isRunning()) {
appiumDriverLocalService.stop();
}
}
private DesiredCapabilities setDesiredCapabilities(){
// Set the desired capabilities
DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
desiredCapabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "iOS");
desiredCapabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "16.4");
desiredCapabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Xcode simulator");
desiredCapabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, "XCUITest");
// Set the path to the app file (.app or .ipa)
desiredCapabilities.setCapability(MobileCapabilityType.APP, "<path-to-iOsApp.app>");
return desiredCapabilities;
}
}
- POM.XML file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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.example</groupId>
<artifactId>ios_test</artifactId>
<version>0.1</version>
<packaging>${packaging}</packaging>
<parent>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-parent</artifactId>
<version>3.9.1</version>
</parent>
<properties>
<packaging>jar</packaging>
<jdk.version>17</jdk.version>
<release.version>17</release.version>
<micronaut.version>3.9.1</micronaut.version>
<exec.mainClass>com.example.Ios_testCommand</exec.mainClass>
</properties>
<repositories>
<repository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>io.appium</groupId>
<artifactId>java-client</artifactId>
<version>8.5.0</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.9.1</version>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-client</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>info.picocli</groupId>
<artifactId>picocli</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-jackson-databind</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut.picocli</groupId>
<artifactId>micronaut-picocli</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.micronaut.test</groupId>
<artifactId>micronaut-test-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.micronaut.build</groupId>
<artifactId>micronaut-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<!-- Uncomment to enable incremental compilation -->
<!-- <useIncrementalCompilation>false</useIncrementalCompilation> -->
<annotationProcessorPaths combine.children="append">
<path>
<groupId>info.picocli</groupId>
<artifactId>picocli-codegen</artifactId>
<version>${picocli.version}</version>
</path>
</annotationProcessorPaths>
<compilerArgs>
<arg>-Amicronaut.processing.group=com.example</arg>
<arg>-Amicronaut.processing.module=ios_test</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
</project>
I have been through a series of issues in the last couple of weeks to make a sample test work so I can learn the basics. But here feel I am stuck. I am new to mobile automation and am unsure how I can fix this one.
I have tried -
- upgrading the server version,
- Make sure the compatibility between Appium Server, java-client & selenium is correct, as explained in some of the other questions that were asked.
- Running the server on different ports, and
- tries various
Capabilities
But I had no luck!
When I run my test, i get the following output:
Connected to the target VM, address: '127.0.0.1:54962', transport: 'socket'
Appium Server started: http://127.0.0.1:4723/
org.openqa.selenium.SessionNotCreatedException: Could not start a new session. Response code 404. Message: The requested resource could not be found, or a request was received using an HTTP method that is not supported by the mapped resource
Host info: host: 'dsa207548', ip: 'fe80:0:0:0:8b6:cd51:acf8:917e%en0'
Build info: version: '4.9.1', revision: 'eb2032df7f'
System info: os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '13.3.1', java.version: '17.0.2'
Driver info: io.appium.java_client.ios.IOSDriver
Command: [null, newSession {capabilities=[{appium:app=<<path-to-iOsApp.app>>, appium:automationName=XCUITest, appium:deviceName=Xcode simulator, platformName=IOS, appium:platformVersion=16.4}], desiredCapabilities=Capabilities {app: <path-to-iOsApp.app>, automationName: XCUITest, deviceName: Xcode simulator, platformName: IOS, platformVersion: 16.4}}]
Capabilities {app: <path-to-iOsApp.app>, automationName: XCUITest, deviceName: Xcode simulator, platformName: IOS, platformVersion: 16.4}
at org.openqa.selenium.remote.ProtocolHandshake.createSession(ProtocolHandshake.java:136)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at io.appium.java_client.remote.AppiumProtocolHandshake.createSession(AppiumProtocolHandshake.java:133)
at io.appium.java_client.remote.AppiumProtocolHandshake.createSession(AppiumProtocolHandshake.java:102)
at io.appium.java_client.remote.AppiumCommandExecutor.createSession(AppiumCommandExecutor.java:182)
at io.appium.java_client.remote.AppiumCommandExecutor.execute(AppiumCommandExecutor.java:250)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:543)
at io.appium.java_client.AppiumDriver.startSession(AppiumDriver.java:274)
at org.openqa.selenium.remote.RemoteWebDriver.<init>(RemoteWebDriver.java:157)
at io.appium.java_client.AppiumDriver.<init>(AppiumDriver.java:89)
at io.appium.java_client.AppiumDriver.<init>(AppiumDriver.java:101)
at io.appium.java_client.ios.IOSDriver.<init>(IOSDriver.java:104)
at com.example.service.AppiumDriverService.startDriver(AppiumDriverService.java:114)
at com.example.service.AppiumDriverService.initDriver(AppiumDriverService.java:42)
at com.example.AppiumDriverServiceTest.setup(AppiumDriverServiceTest.java:18)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.RunBefores.invokeMethod(RunBefores.java:33)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
When I was debugging the test, I observed that after appiumDriverLocalService.start();
the appium server status appears to be this -
{"status":9,"value":{"error":"unknown command","message":"The requested resource could not be found, or a request was received using an HTTP method that is not supported by the mapped resource","stacktrace":""}}
And the value of -
appiumDriverLocalService.isRunning()
is
true
.