I've wanted to write a Selenium Grid app in Java.
On http://localhost:4444/grid/console it says that the node is connected to the hub.
On the client-side I've wanted to write the following:
try {
DesiredCapabilities capability = DesiredCapabilities.firefox();
WebDriver driver = new RemoteWebDriver(new URL("http://IP of Hub:4444/wd/hub"), capability);
capability.setBrowserName("firefox");
driver.get("https://www.google.com");
} catch (MalformedURLException ex) {
System.err.println("URL Exception: "+ex.getMessage());
}
Unfortunately, the following exception was thrown when running the client app:
Exception in thread "main" org.openqa.selenium.SessionNotCreatedException: invalid argument: can't kill an exited process
...
Driver info: driver.version: unknown
Provide geckodriver path before initializing a webdriver instance,
try {
DesiredCapabilities capability = DesiredCapabilities.firefox();
System.setProperty("webdriver.gecko.driver", "/PATH_OF_DRIVER/geckodriver.exe");
driver = new RemoteWebDriver(new URL("http://Hub_IP/wd/hub"), capability);
capability.setBrowserName("firefox");
driver.get("https://www.google.com");
} catch (MalformedURLException ex) {
System.err.println("URL Exception: "+ex.getMessage());
}
Solution: There was something wrong with the geckodriver in Linux (node).
I added a node on a Windows PC and it worked.
I get the following error when I run with command: ./gradlew clean runTests
Local on windows: OKI
On TeamCity in Linux: .driverSetUp FAILED
java.lang.IllegalStateException
INFO[newLocalDriver] INFO Creating driver with options
ro.automation.canalLaDistanta.Achizitie_DeviceSTD.driverSetUp FAILED
This is my code.
public WebDriver newLocalDriver() {
System.setProperty("webdriver.chrome.driver", getChromeDriverPath());
ChromeOptions options = new ChromeOptions();
options.setBinary(getChromeBinaryPath());
options.addArguments("--no-default-browser-check");
options.addArguments("window-size=1280,960");
options.setHeadless(false);
options.addArguments("start-maximized");
log4j.info("Creating driver with options");
ChromeDriver localChromeDriver = new ChromeDriver(options);
log4j.info("Driver created: " + localChromeDriver);
return localChromeDriver;
}
private String getChromeDriverPath() {
String chromeDriverPath = null;
System.out.println(operatingSystem);
if (operatingSystem.contains("windows")) {
chromeDriverPath = "resources/browser/chromeDriver-windows/chromedriver.exe";
System.out.println("+++ Windows ChromeDriver found! +++");
} else if (operatingSystem.contains("linux")) {
chromeDriverPath = "resources/browser/chromeDriver-linux/chromedriver";
System.out.println("+++ Linux ChromeDriver found! +++");
} else System.out.println("OS does not match with Windows or Linux");
return chromeDriverPath;
Im trying to start Appium server programmatically from Java
(OS: Windows7 x64)
using first method from source: http://www.automationtestinghub.com/3-ways-to-start-appium-server-from-java/
The code that I use for starting Appium sever is:
public void startServer() {
//Set Capabilities
cap = new DesiredCapabilities();
cap.setCapability("noReset", "false");
//Build the Appium service
builder = new AppiumServiceBuilder();
builder.withIPAddress("127.0.0.1");
builder.usingPort(4723);
builder.withCapabilities(cap);
builder.withArgument(GeneralServerFlag.SESSION_OVERRIDE);
builder.withArgument(GeneralServerFlag.LOG_LEVEL, "error");
//added by myself:
builder.usingDriverExecutable(new File("C:/node/node.exe"));
builder.withAppiumJS(new File("C:/Users/[user]/AppData/Roaming/npm/node_modules/appium/lib/appium.js"));
//Start the server with the builder
service = AppiumDriverLocalService.buildService(builder);
service.start();
}
I'm getting an exception:
Exception in thread "main" io.appium.java_client.service.local.AppiumServerHasNotBeenStartedLocallyException: The local appium server has not been started. The given Node.js executable: C:\node\node.exe Arguments: [C:\Users\Dima\AppData\Roaming\npm\node_modules\appium\lib\appium.js, --port, 4723, --address, 127.0.0.1, --log-level, error, --session-override, --default-capabilities, {\"noReset\": \"false\"}]
Process output: C:\Users[user]\AppData\Roaming\npm\node_modules\appium\lib\appium.js:1
(function (exports, require, module, __filename, __dirname) { import _ from 'lodash'; ^^^^^^
SyntaxError: Unexpected token import
at createScript (vm.js:80:10)
at Object.runInThisContext (vm.js:139:10)
at Module._compile (module.js:616:28)
at Object.Module._extensions..js (module.js:663:10)
at Module.load (module.js:565:32)
at tryModuleLoad (module.js:505:12)
at Function.Module._load (module.js:497:3)
at Function.Module.runMain (module.js:693:10)
at startup (bootstrap_node.js:188:16)
at bootstrap_node.js:609:3
I tried every way to start Appium server from the source, but second one causes to the same, but third causes to error
Any ideas? Thanks to all in advance!
Take a look at official documentation:
https://github.com/appium/java-client/blob/master/docs/The-starting-of-an-app-using-Appium-node-server-started-programmatically.md
Make sure your env setup for Appium is correct and that appium service/client versions are compatible.
It did mistake in code. Fixed method is:
public static String runAppiumService(int appiumPort) {
//Build parameters for appium server:
AppiumServiceBuilder appiumServiceBuilder = new AppiumServiceBuilder();
appiumServiceBuilder.usingPort(appiumPort)
.withIPAddress(APPIUM_IP)
.withAppiumJS(new File(getAppiumJsPath()))
.withArgument(GeneralServerFlag.SESSION_OVERRIDE)
.withLogFile(new File(System.getProperty("user.dir") + "/target/resources/appium_server_logs" + Thread.currentThread().getId()));
AppiumDriverLocalService service = AppiumDriverLocalService.buildService(appiumServiceBuilder);
service.start();
}
public class ServerManager {
AppiumDriverLocalService service;
public static void main(String args[]) {
ServerManager sm = new ServerManager();
sm.startServer();
}
public void startServer() {
final DesiredCapabilities cap = new DesiredCapabilities();
//Set Capabilities
cap.setCapability("noReset", "false");
//Build the Appium service
AppiumServiceBuilder builder = new AppiumServiceBuilder();
builder = new AppiumServiceBuilder();
builder.withIPAddress("127.0.0.1");
builder.usingPort(4723);
builder.withCapabilities(cap);
builder.withArgument(GeneralServerFlag.SESSION_OVERRIDE);
builder.withArgument(GeneralServerFlag.LOG_LEVEL,"error");
//Start the server with the builder
service = AppiumDriverLocalService.buildService(builder);
service = AppiumDriverLocalService.buildService(builder);
service.start();
}
public void stopServer() {
service.stop();
}
}
I am unable to automate my tests parallelly in an Android platform with multiple mobile devices.
If I connect 2 devices to my system and provide capabilities like mobile device Name and version, It is executing in the device which is recognized first through ADB.
If try to start the appium servers with different ports,
new AppiumServiceBuilder().usingAnyFreePort() I am getting Null pointer Exception.
[36minfo[39m: Appium REST http interface listener started on 0.0.0.0:2583
[36minfo[39m: [debug] Non-default server args: {"port":2583}
1) How to override session with AppiumServiceBuilder()
2) How to Restrict appium to execute on the device which is provided with capabilities, even 2 or more devices are connected.
My Code:
public class ApiumMain {
public static void main(String[] args) {
new Thread( new Device_Thread( "4897bb00", "6.0.1" ) ).start();
// new Thread( new Device_Thread( "TA64301YVY", "5.0.1" ) ).start();
}
}
public class Device_Thread extends ApiumMain implements Runnable {
public String mobileDeviceName;
public String androidVersion;
public Device_Thread( String mobile, String version ) {
mobileDeviceName = mobile;
androidVersion = version;
}
#Override
public void run() {
String hsotMachineIP = "127.0.0.1";
Integer seleniumProt = 4723; /*Default {"port":4723}*/
String nodeJSExecutable = "C:\\Program Files (x86)\\Appium\\node.exe";
String appiumJS = "C:\\Program Files (x86)\\Appium\\node_modules\\appium\\bin\\appium.js";
Integer nodeJSPort = (int)( Math.random() * 8000 ) + 1000;
startAppium(nodeJSExecutable, nodeJSPort, appiumJS, mobileDeviceName, androidVersion, hsotMachineIP, seleniumProt);
}
public void startAppium(String nodeJSExecutable, int nodeJSPort, String appiumJS,
String mobileDeviceName, String androidVersion, String hsotMachineIP, int seleniumProt ) {
RemoteWebDriver driver = null;
String appURL = "http://www.w3schools.com/";
// http://appium.io/slate/en/master/?java#appium-server-capabilities
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("automationName", "Appium" );
capabilities.setCapability("platformName", "Android");
capabilities.setCapability("platformVersion", androidVersion );
capabilities.setCapability("deviceName", mobileDeviceName );
capabilities.setCapability("app", "chrome");
capabilities.setCapability("browserName", "chrome");
capabilities.setCapability("newCommandTimeout", "0");
// ANDROID ONLY
/*capabilities.setCapability("appActivity", "com.android");
capabilities.setCapability("appPackage", ".ApiumMain");
*/
// Appium servers are nothing but the Node.js server
AppiumDriverLocalService service = AppiumDriverLocalService.buildService(
new AppiumServiceBuilder()
.usingDriverExecutable( new File( nodeJSExecutable ) )
.withAppiumJS( new File( appiumJS ) )
);
service.start();
System.out.println( "Device : " + mobileDeviceName );
try {
String url = String.format("http://%s:%d/wd/hub", hsotMachineIP, seleniumProt);
System.out.println(" Server Address : " + url );
driver = new RemoteWebDriver( new URL( url ), capabilities );
driver.get( appURL );
browserActions( driver, appURL );
}catch (MalformedURLException e) {
e.printStackTrace();
} finally {
driver.quit();
service.stop();
}
}
private void browserActions(RemoteWebDriver driver, String appURL) {
try {
WebElement ele = driver.findElementByXPath("//body/div[4]/div[1]/div[1]/a[1]");
ele.click();
WebElement ele2 = driver.findElementByXPath("//*[#id='topnav']/div[1]/div[1]/a[2]");
ele2.click();
System.in.read();
System.in.read();
} catch (ElementNotVisibleException logMsg){
} catch (IOException e) {
}
}
}
Appium setup for Windows:
Installed Android SDK, Appium [Server & java-client], Add ADT pugin to Eclipse IDE and Selenium-server-standalone
set Environment Variables:
AVA_HOME~C:\Program Files (x86)\Java\jdk1.8.0_66
ANDROID_HOME~D:\Android\sdk
Path~D:\Android\sdk;D:\Android\sdk\platform-tools - ADB Debugger
Running multiple Appium sessions with different Server flags for Parallel Android Tests
Appium is an open-source tool for automating native, mobile web, and hybrid applications on IOS and Android platforms.
Appium client libraries wraps around Selenium client libraries with some extra commands added to controlling mobile devices
Client: The machine on which the WebDriver[HTTP Client] API is being used to communicate with server through commands.
Appium Client implements the "Mobile JSONWP" to extend "JSONWP". The Mobile JSONWP is for automation of native and hybrid mobile applications and JSONWP is for automating web-browser applications.
Commands:Each HTTP request with a method and template defined in this specification represents a single command and therefore each command produces a single HTTP response. Client initiates a session with server using desired capabilities via JSON. Based on the browser session ID and Selenium remoteServerAddress the communication takes place through Http Rest API.
Selenium Source of HTTP Client:
HttpClient.Factory httpClientFactory = new ApacheHttpClient.Factory();
HttpClient client = httpClientFactory.createClient(remoteServerAddress);
HttpRequest httpRequest = commandCodec.encode(command);
HttpResponse httpResponse = client.execute(httpRequest, true);
Response response = responseCodec.decode(httpResponse);
Server: Before starting any mobile tests you must start the servers like RemoteWebDriver & Appium|NodeJS.
AppiumServer - REST API written in Node.js
SeleniumRCServer - The Selenium server receives Selenium commands from your test program using HTTP GET/POST requests, interprets and executes those commands, and reports back the results to your program.
Connect couple of android devices to the system and run below adb shell commands
D:\Yash>adb devices
List of devices attached
TA64301YVY device
4897bb00 device
D:\Yash>adb -s TA64301YVY shell getprop ro.build.version.release
5.1
D:\Yash>adb -s TA64301YVY shell getprop > D:\Yash\cmdOUT.txt
+----------------------------+------------+--------------+
|[net.bt.name]: | [Android] | [Android] |
|[ro.boot.serialno]: | [4897bb00] | [TA64301YVY] |
|[ro.product.brand]: | [samsung] | [motorola] |
|[ro.product.model]: | [SM-G900F] | [XT1052] |
|[ro.build.version.release]: | [6.0.1] | [5.1] |
+----------------------------+------------+--------------+
Q1 - Ans: To override a session with AppiumServiceBuilder use this argument "GeneralServerFlag.SESSION_OVERRIDE". presence of an arguments means "true"
Q2 - Ans: If we are not providing UDID (OR) RemoteAddress then Driver will connect to first device which is detected by ADB. If we want to restrict appium to connect specific named physical device in the list of connected devices use UDID-Unique device identifier.
JAVA Parallel Android Tests to automate mobile web apps [java-client-4.1.1.jar]:
nodeJSExec « [C:\Program Files (x86)\Appium\node.exe]
nodeJSArgs « [C:\Program Files (x86)\Appium\node_modules\appium\bin\appium.js, --port, 1750, --address, 127.0.0.1, --log, D:\Yash\MyAppiumConsole_4897bb00.txt, --chromedriver-port, 7115, --bootstrap-port, 7119, --session-override]
public void startAppium(String nodeJSExecutable, int nodeJSPort, String appiumJS, String mobileDeviceName,
String androidVersion, String hsotMachineIP ) {
RemoteWebDriver driver = null;
String appURL = "http://www.w3schools.com/";
File logFile = new File("D:/Yash/MyAppiumConsole_"+mobileDeviceName+".txt");
File javaConsole = new File("D:/Yash/MyJavaConsole_"+mobileDeviceName+".txt");
systemConsole2File( javaConsole );
/*The hub only reads browserName, version, platform and applicationName.
The other capabilities (deviceName, platformVersion, platformName, ...) are Appium capabilities, not used by the hub.*/
// Proxying straight through to Chromedriver
DesiredCapabilities capabilities = DesiredCapabilities.android();
/* Appium - io.appium.java_client.remote */
capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, "Appium" );
capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, androidVersion );
capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, mobileDeviceName );
capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, "chrome"); // "Browser"
capabilities.setCapability(MobileCapabilityType.UDID, mobileDeviceName);
/* Selenium - org.openqa.selenium.remote */
capabilities.setCapability(CapabilityType.TAKES_SCREENSHOT, "true");
// Appium servers are nothing but the Node.js server
AppiumDriverLocalService service = AppiumDriverLocalService.buildService(
new AppiumServiceBuilder()
.withAppiumJS( new File( appiumJS ) )
.usingDriverExecutable( new File( nodeJSExecutable ) )
.usingPort( nodeJSPort )
.withIPAddress( hsotMachineIP )
.withArgument(GeneralServerFlag.SESSION_OVERRIDE)
.withArgument(AndroidServerFlag.BOOTSTRAP_PORT_NUMBER, nextFreePort().toString())
.withArgument(AndroidServerFlag.CHROME_DRIVER_PORT, nextFreePort().toString())
.withLogFile(logFile)
);
service.start();
System.out.println(" Appium Server Address [Local]: " + service.getUrl() );
driver = new RemoteWebDriver( service.getUrl(), capabilities );
...
}
public static final int HIGHEST_PORT = 65535;
public static final int LEAST_PORT = 1024;
public static Integer nextFreePort() {
Integer port = (int)( Math.random() * 8000 ) + LEAST_PORT;
while (true) {
try ( ServerSocket endpoint = new ServerSocket(port) ) {
System.out.println("Local Port on which this socket is listening :"+port);
return port;
} catch (IOException e) {
port = ThreadLocalRandom.current().nextInt();
}
}
}
public static void systemConsole2File( File logFile ) {
try ( FileOutputStream fos = new FileOutputStream( logFile );
PrintStream system_console = new PrintStream( fos )
) {
System.setOut( system_console ); // output stream.
System.setErr( system_console ); // error output stream.
} catch (IOException e) {
e.printStackTrace();
}
}
Appium log with endpoints from the node where script is executed:
<?-- APPIUM_NODEJS_LISTENING_PORT = 4723 SERVERS <--port, --callback-port 4723>
Mobile « http://127.0.0.1:4723/wd/hub
Desktop « http://localhost:4444/wd/hub
-->
[36minfo[39m: Appium REST http interface listener started on 127.0.0.1:1750
[36minfo[39m: [debug] Non-default server args:
{
"address":"127.0.0.1",
"port":1750,
"bootstrapPort":7119,
"sessionOverride":true,
"log":"D:\\Yash\\MyConsole_TA64301YVY.txt",
"chromeDriverPort":7115
}
<?-- LIST OF CONNECTED DEVICES [UDID]
Unique device identifier of the connected physical device
To connect specific named device in the list of connected devices use UDID
-->
[36minfo[39m: [debug] Trying to find a connected android device
[36minfo[39m: [debug] Getting connected devices...
[36minfo[39m: [debug] executing cmd: D:\Android\sdk\platform-tools\adb.exe devices
[36minfo[39m: [debug] 2 device(s) connected
[36minfo[39m: Found device TA64301YVY
[36minfo[39m: [debug] Setting device id to TA64301YVY
<?--
BOOTSTRAP = 4724 Socket tcp port to use on device to talk to Appium
« Forwarding system:4724 to device:4724 appium bootstrap to device
-->
[36minfo[39m: [debug] Forwarding system:7119 to device:4724
[36minfo[39m: [debug] executing cmd: D:\Android\sdk\platform-tools\adb.exe -s TA64301YVY forward tcp:7119 tcp:4724
[36minfo[39m: [debug] Pushing appium bootstrap to device...
<?--
Chrome debugger server to connect to, in the form of <hostname/ip:port>
CHROME_DRIVER = 9515 Port upon which ChromeDriver will run
-->
[36minfo[39m: Chromedriver: Spawning chromedriver with: C:\Program Files (x86)\Appium\node_modules\appium\node_modules\appium-chromedriver\chromedriver\win\chromedriver.exe --url-base=wd/hub --port=7115
[36minfo[39m: Chromedriver: [STDOUT] Starting ChromeDriver 2.18.343845 (73dd713ba7fbfb73cbb514e62641d8c96a94682a) on port 7115
APPLICATION URL:
[36minfo[39m: JSONWP Proxy: Proxying [POST /wd/hub/session/SESSION-ID/url] to [POST http://127.0.0.1:7115/wd/hub/session/SESSION-ID/url] with body: {"url":"http://www.w3schools.com/"}
[36minfo[39m: JSONWP Proxy: Got response with status 200: {"sessionId":"SESSION-ID","status":0,"value":null}
WEB ELEMENT:
[36minfo[39m: JSONWP Proxy: Proxying [POST /wd/hub/session/SESSION-ID/element] to [POST http://127.0.0.1:7115/wd/hub/session/SESSION-ID/element] with body: {"using":"xpath","value":"//body/div[4]/div[1]/div[1]/a[1]"}
[36minfo[39m: JSONWP Proxy: Got response with status 200: {"sessionId":"SESSION-ID","status":0,"value":{"ELEMENT":"0.39628730167672455-1"}}
WEB ELEMENT & ACTION:
[36minfo[39m: JSONWP Proxy: Proxying [POST /wd/hub/session/SESSION-ID/element/0.39628730167672455-1/click] to [POST http://127.0.0.1:7115/wd/hub/session/SESSION-ID/element/0.39628730167672455-1/click] with body: {"id":"0.39628730167672455-1"}
[36minfo[39m: JSONWP Proxy: Got response with status 200: {"sessionId":"SESSION-ID","status":0,"value":null}
I just create a sample code as below which is used to launch the calculator apk file and perform some task
#BeforeSuite
public static void driverInitalize() throws Exception {
try {
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("deviceName", "Android Emulator");
capabilities.setCapability("platformName", "Android");
capabilities.setCapability("platformVersion", "4.2.2");
// capabilities.setCapability("browserName", "Chrome");
capabilities.setCapability("appPackage", "com.android.calculator2");
capabilities.setCapability("appActivity", "com.android.calculator2.Calculator");
capabilities
.setCapability("app",
"C:\\Ecare\\Appium\\com.android.calculator2-5.1-1720659-22-minAPI22.apk");
driver = new RemoteWebDriver(
new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
} catch (Exception ex) {
ex.printStackTrace();
}
}
#Test
public static void sampleTest1() throws Exception {
try {
// System.out.println(driver.getTitle());
driver.findElement(By.xpath(".//*[contains(text(),'7')]")).click();
driver.findElement(By.xpath(".//*[contains(text(),'+')]")).click();
driver.findElement(By.xpath(".//*[contains(text(),'3')]")).click();
driver.findElement(By.xpath(".//*[contains(text(),'=')]")).click();
String value = driver.findElement(
By.className("android.widget.EditText")).getText();
System.out.print(value);
} catch (Exception ex) {
ex.printStackTrace();
}
}
#AfterSuite
public static void tearDown() throws Exception {
try {
driver.quit();
} catch (Exception ex) {
ex.printStackTrace();
}
}
Whenever I executed the above code will return following exception in appium server as well as in eclipse IDE. Can somebody tell me how can I overcome this issue. It seems to be the session is progress but I'm not sure how to kill the progress session which is started earlier. I tried to start up the appium server as appium --no-reset, and checked in the override existing session as well but no luck.
Failure [INSTALL_FAILED_OLDER_SDK]
> at C:\Program Files (x86)\Appium\node_modules\appium\node_modules\appium-adb\lib\adb.js:1358:17
> at [object Object].<anonymous> (C:\Program Files (x86)\Appium\node_modules\appium\node_modules\appium-adb\lib\adb.js:180:9)
> at ChildProcess.exithandler (child_process.js:635:7)
> at ChildProcess.EventEmitter.emit (events.js:98:17)
> at maybeClose (child_process.js:743:16)
> at Process.ChildProcess._handle.onexit (child_process.js:810:5)
> info: [debug] Responding to client with error: {"status":33,"value":{"message":"A new session could not be created. (Original error: Remote install failed: pkg: /data/local/tmp/b23beec2f0794d869eb021f75e3791bd.apk\r\r\nFailure [INSTALL_FAILED_OLDER_SDK])","origValue":"Remote install failed: pkg: /data/local/tmp/b23beec2f0794d869eb021f75e3791bd.apk\r\r\nFailure [INSTALL_FAILED_OLDER_SDK]"},"sessionId":null}
> info: <-- POST /wd/hub/session 500 39088.716 ms - 362
Please help me out.
The error you are getting [INSTALL_FAILED_OLDER_SDK] is caused due to the version of android of your avd/device is older than the version being used to compile the code of the app.
Check the target sdk version and the minimum sdk version of the app.
if you have the access to the source code of the app these information will be in the manifest file in the android:minSdkVersion tag.