Skip to content

How to start an AppiumDriver locally

Sombrio edited this page Dec 21, 2017 · 8 revisions

Requirements

  • Installed Node.js.

  • At least an appium server instance installed via npm.

Which capabilities these features provide

There are abilities and options of the starting of a local Appium node server. End users are free to launch a local Appium node server and open their app for the further testing the following way:

DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.SetCapability(MobileCapabilityType.PlatformVersion, "6.0");
capabilities.SetCapability(MobileCapabilityType.DeviceName, "Android Emulator");
capabilities.SetCapability(MobileCapabilityType.App, app);
driver = new AndroidDriver<AppiumWebElement>(capabilities, timeSpanForTheResponse);        

How to prepare the local service before the starting

If there is no specific parameters then

using OpenQA.Selenium.Appium.Service;
...

AppiumLocalService service = AppiumLocalService.BuildDefaultService();
service.Start();
 ...
service.Dispose();

Requirements(!!!):

  • make sure that the path to node.js is defined at the PATH environmental variable and there is an Appium server instance installed via NPM

OR

  • please set up the NODE_BINARY_PATH environmental variable. Here should a full path to the node.js executable file. This usecase is very useful for platforms which differ from Windows. There are possible unpredictable issues related to user's environmental settings. Also it is useful then the instance of non-default (it is not defined at the PATH, it is the another node.js modification such as NSolod and so on) node.js is required. Also it is possible to define the path to not default appium.js or main.js via APPIUM_BINARY_PATH environmental variable.

It is possible to perform this usecase programmatically this way:

using OpenQA.Selenium.Appium.Service;
using System;
...

Environment.SetEnvironmentVariable(AppiumServiceConstants.NodeBinaryPath, "the full path to node.js executable file");
Environment.SetEnvironmentVariable(AppiumServiceConstants.AppiumBinaryPath, "the full path to appium.js or main.js");
AppiumLocalService service = AppiumLocalService.BuildDefaultService();
service.Start();
 ...
service.Dispose();

If there should be non default parameters specified then

If non localhost IP address is required then

using OpenQA.Selenium.Appium.Service;
...

AppiumLocalService service = new AppiumServiceBuilder().WithIPAddress("listenableIP").
                Build();
service.Start();
 ...
service.Dispose();

If the the log file is required for server output

using OpenQA.Selenium.Appium.Service;
using System.IO;
...

AppiumLocalService service = new AppiumServiceBuilder().
WithLogFile(new FileInfo("path\to\log\file")).Build();
service.Start();
 ...
service.Dispose();

If it needs for the port which differs from 4723 then

using OpenQA.Selenium.Appium.Service;
...

AppiumLocalService service = new AppiumServiceBuilder().UsingPort(4000).Build();
service.Start();
 ...
service.Dispose();

or

using OpenQA.Selenium.Appium.Service;
...

AppiumLocalService service = new AppiumServiceBuilder().UsingAnyFreePort().Build();
service.Start();
 ...
service.Dispose();

If it needs to define other server parameters then

using OpenQA.Selenium.Appium.Service;
using OpenQA.Selenium.Appium.Service.Options;
...

OptionCollector args = new OptionCollector().AddArguments(GeneralOptionList.LogNoColors());
AppiumLocalService service = new AppiumServiceBuilder().WithArguments(args).Build();
service.Start();
 ...
service.Dispose();

Actual server flags are listed here. In order to use them easyly they are listed by:

  • OpenQA.Selenium.Appium.Service.Options.GeneralOptionList - here are common server options
  • OpenQA.Selenium.Appium.Service.Options.AndroidOptionList - here are Android-specific server options
  • OpenQA.Selenium.Appium.Service.Options.IOSOptionList - here are iOS-specific server options

Boolean arguments have no parameters. Other server flags require not empty string values.

Also it is possible to define default capabilities

This feature is compatible with Appium node server v >= 1.5.x. t is possible to do something like that:

DesiredCapabilities serverCapabilities = new DesiredCapabilities();
//the filling of server default capabilities is going below

DesiredCapabilities clientCapabilities = new DesiredCapabilities();
//the filling of server default capabilities is going below

OptionCollector argCollector = new OptionCollector().AddCapabilities(serverCapabilities);
AppiumServiceBuilder builder = new AppiumServiceBuilder().WithArguments(argCollector);
AppiumLocalService service = builder.WithArguments(args).Build();

then

AndroidDriver<AppiumWebElement> driver = new AndroidDriver<AppiumWebElement>
(service, clientCapabilities);

or

AndroidDriver<AppiumWebElement> driver = new AndroidDriver<AppiumWebElement>
(builder, clientCapabilities);

or

service.Start();
AndroidDriver<AppiumWebElement> driver = new AndroidDriver<AppiumWebElement>
(service.getUrl(), clientCapabilities);

The full list of capabilities is described here: https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md. There are three classes that help to define values of capabilities: OpenQA.Selenium.Appium.Enums.remote.MobileCapabilityType OpenQA.Selenium.Appium.Enums.AndroidMobileCapabilityType OpenQA.Selenium.Appium.Enums.IOSMobileCapabilityType

If it needs to override the default file path to node.js executable and/or the path to appium.js or main.js then

using OpenQA.Selenium.Appium.Service;
...

AppiumLocalService service = new AppiumServiceBuilder().
WithAppiumJS(new FileInfo("the path to the desired appium.js or main.js")).
UsingDriverExecutable("the path to the desired node.js executable file").Build();
service.Start();
 ...
service.Dispose();

How to create an AppiumDriver instance

The common constructors are still available

public AppiumDriver(Uri remoteAddress, ICapabilities desiredCapabilities, TimeSpan commandTimeout)

public AppiumDriver(Uri remoteAddress, ICapabilities desiredCapabilities)

There are new constructors:

public AppiumDriver(AppiumLocalService service, ICapabilities desiredCapabilities, TimeSpan commandTimeout)

public AppiumDriver(AppiumLocalService service, ICapabilities desiredCapabilities)

public AppiumDriver(AppiumServiceBuilder builder, ICapabilities desiredCapabilities, TimeSpan commandTimeout)

public AppiumDriver(AppiumServiceBuilder builder, ICapabilities desiredCapabilities)

public AppiumDriver(ICapabilities desiredCapabilities, TimeSpan commandTimeout)

public AppiumDriver(ICapabilities desiredCapabilities)

An instance of AppiumLocalService which has passed through constructors will be stopped when

  driver.Quit();

If there is need to keep the service alive during a long time then something like that is available

  service.Start();
  
  ....

  new IOSDriver<AppiumWebElement>(service.ServiceUrl, capabilities, commandTimeout)

The known issue

This case can cause problems

TimeSpan timeOutOfTheWaitingForASimulator //(!!!);
...
AppiumServiceBuilder builder = new AppiumServiceBuilder();
OptionCollector collector = new OptionCollector().AddArguments(IOSOptionList.LaunchTimeout(Convert.
ToString(timeOutOfTheWaitingForASimulator.TotalMilliseconds)));
AppiumLocalService localService = builder.WithArguments(collector).Build();
  
  ....
TimeSpan  commandTimeout; //imagine that this timeout is much lesser than 
//timeOutOfTheWaitingForASimulator 

new IOSDriver<AppiumWebElement>(localService.ServiceUrl, capabilities, commandTimeout)
//or
//new IOSDriver<AppiumWebElement>(localService, capabilities, commandTimeout)
//here the starting of IOSDriver may be failed

So a command timeout and an iOS Simulator launching timeout should be synchronized for now. This issue may be fixed further.