We have learnt from our earlier post Appium test run, how to write appium test, now to run the appium tests we need to start the appium server,
Problem:
let’s say that we have to schedule our appium tests to run (may be a nightly build test) from a computer or schedule the run using jenkins CICD pipelines like jenkins or ADO, then it’s difficult to start the server manually as we might not be at the same time near to machine.
Solution:
Appium provided couple of classes to run the appium server programmatically using java,
- AppiumServiceBuilder
- AppiumDriverLocalService
By using the builder, we can set parameters like ipAddress, Port, logFileName etc, and then build the parameters so the Service can start the server, even we can stop the appium server whenever we want.
Prerequisites:
- You should install node.exe [from nodejs.org]
node executable path for –
Windows OS –
C:\Program Files\nodejs
Mac OS –
/usr/local/bin/node
- Appium should be installed
There are 2 ways we can start the appium server manually
- Using Appium GUI (if using appium 1.x)
- Using Appium CLI in terminal (for both appium CLI 1.x and 2.x)
sudo npm install -g appium
or
sudo npm install -g appium@next
Note – the path of appium.js / appium executable file which we will use in our code [depends on the appium installation, by GUI or npm command ]
Appium executable path –
Windows OS –
C:\Users\[MyUser]\AppData\Roaming\npm\node_modules\appium\lib\
or
C:\Users\[MyUser]\AppData\Local\Programs\appium-desktop\resources\app\node_modules\appium\build\lib
Mac OS –
/usr/local/bin/appium
//for appium 2.x
or
/Applications/Appium Server GUI.app/Contents/Resources/app/node_modules/appium/lib/appium.js
//if using appium 1.x with appium desktop
AppiumServiceBuilder builder = new AppiumServiceBuilder(); builder .withAppiumJS(new File("/usr/local/bin/appium")) .usingDriverExecutable(new File("/usr/local/bin/node")) //.usingAnyFreePort() //.withIPAddress("127.0.0.1") .usingPort(4723) .withEnvironment(environment) .withArgument(GeneralServerFlag.LOCAL_TIMEZONE) //.withArgument(GeneralServerFlag.LOG_LEVEL, "WARN") .withLogFile(new File("AppiumLog.txt")); server = AppiumDriverLocalService.buildService(builder);
server.start() – to start the appium server
server.stop() – to stop the server
For older version of appium i.e – 1.x with java-client v8
we need to add .withArgument(GeneralServerFlag.BASEPATH, "/wd/hub")
AppiumServiceBuilder builder = new AppiumServiceBuilder(); builder .withAppiumJS(new File("/usr/local/bin/appium")) .usingDriverExecutable(new File("/usr/local/bin/node")) //.usingAnyFreePort() //.withIPAddress("127.0.0.1") .usingPort(4723) .withEnvironment(environment) .withArgument(GeneralServerFlag.LOCAL_TIMEZONE) //.withArgument(GeneralServerFlag.LOG_LEVEL, "WARN") .withArgument(GeneralServerFlag.BASEPATH, "/wd/hub") .withLogFile(new File("AppiumLog.txt")); server = AppiumDriverLocalService.buildService(builder);
Detailed code block here –
package base; 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 java.io.File; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.util.HashMap; public class AppiumServer { static AppiumDriverLocalService server; public static void Start(){ if(isPortAvailable(4723)){ getInstance().start(); System.out.println("Server started from here!"); }else System.out.println("Server already running!"); } static AppiumDriverLocalService getInstance(){ if(server == null){ setInstance(); server.clearOutPutStreams(); //stop printing appium logs to console } return server; } static void setInstance(){ HashMap<String, String> environment = new HashMap(); //path to carthage environment.put("PATH", "/usr/local/bin:" + System.getenv("PATH")); AppiumServiceBuilder builder = new AppiumServiceBuilder(); builder .withAppiumJS(new File("/usr/local/bin/appium")) .usingDriverExecutable(new File("/usr/local/bin/node")) //.usingAnyFreePort() .withIPAddress("127.0.0.1") .usingPort(4723) .withEnvironment(environment) .withArgument(GeneralServerFlag.LOCAL_TIMEZONE) //.withArgument(GeneralServerFlag.LOG_LEVEL, "WARN") .withLogFile(new File("AppiumLog.txt")); server = AppiumDriverLocalService.buildService(builder); } public static boolean isPortAvailable(int port) { //applicable for tcp ports try (ServerSocket serverSocket = new ServerSocket()) { // setReuseAddress(false) is required only on OSX, // otherwise the code will not work correctly on that platform serverSocket.setReuseAddress(false); serverSocket.bind(new InetSocketAddress(InetAddress.getByName("localhost"), port), 1); return true; } catch (Exception ex) { return false; } } public static void Stop(){ if(server != null){ getInstance().stop(); System.out.println("Appium server stopped!"); } /*Runtime runtime = Runtime.getRuntime(); try { //runtime.exec("taskkill /F /IM node"); String[] command={"/usr/bin/killall", "-9", "node" }; runtime.exec(command); //runtime.exec("/usr/bin/killall node"); System.out.println("Server stopped!"); } catch (IOException e) { e.printStackTrace(); }*/ } }
Code implementation
AppiumServer.Start()
– to start the appium server
AppiumServer.Stop()
– to stop the appium server.
The appium server logs can be found under Project Directory / AppiumLog.txt
Complete code base with usage cane be found on github – AppiumServer
For the list of appium server arguments, refer https://appium.io/docs/en/writing-running-appium/server-args/
Reference –
https://github.com/appium/java-client/blob/master/docs/The-starting-of-an-Android-app.md
A detailed explanation of this code can be found here –
Part 1 –
Part 2 –