How to start an AppiumDriver locally
-
Installed Node.js.
-
At least an appium server instance installed via npm.
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);
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();
using OpenQA.Selenium.Appium.Service;
...
AppiumLocalService service = new AppiumServiceBuilder().WithIPAddress("listenableIP").
Build();
service.Start();
...
service.Dispose();
using OpenQA.Selenium.Appium.Service;
using System.IO;
...
AppiumLocalService service = new AppiumServiceBuilder().
WithLogFile(new FileInfo("path\to\log\file")).Build();
service.Start();
...
service.Dispose();
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();
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.
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();
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)
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.