Speed Up iOS Appium Test Automation

vector-frameworks-appium_2x

     Appium users have the question like how to speed up the iOS tests, citing the length of time it takes to start tests which use the WebDriverAgent library (all tests using the XCUITest driver).

     Most of the perceived speed of an Appium test can’t be improved due to the base speed of booting devices or the UI actions themselves. The slowest part, which users were asking how to avoid, is the initial startup of a test: the time between sending the first POST /session command and the response indicating that your test script can begin sending commands. We can call this time period the “session creation” time.

     There are desired capabilities we can specify to greatly reduce the time it takes to create a session. Appium is built to cater to a large number of devices, for use in many different situations, but we also want to make sure that it is easy to get started automating your first test. When specifying desired capabilities, Appium will analyze the state of your system and choose default values for every desired capability which you don’t specify. By being more specific, we can have Appium skip the work it does to choose the default values.

     Our first improvement is to set the app location to a file already on the host device. Then you can directly use the bundleId 

caps.setCapability(“bundleId”, “io.test.app”);

      Please ignore the remote path of your application in the code instead of that you can use the local application path, once it gets installed on the device avoid the local path and stick to use bundleId

     Running the tests, it’s easy to notice that the app gets reinstalled on the device for each test. This takes a lot of time and can be skipped. You may have certain tests which require a fresh install or need all the app data cleaned, but those tests could be put into a separate suite, leaving the majority of tests to run faster by reusing the same app. Most users should be familiar with the noReset desired capability.

 caps.setCapability(“noReset”, true)

    Appium uses the simctl command-line tool provided by Apple to match the deviceName desired capability to the udid of the device. We can skip this step by specifying the device udid ourselves.

caps.setCapability(“udid”, “009D802528AB4A1BA7C885A9F6FDBE95”);

      When loading the WedDriverAgent server, Appium loads the files from wherever XCode saved it after compilation. This location is called the “Derived Data Directory” and Appium executes an xcodebuild command in order to get the location. Below desired capability derivedDataPath allowing Appium to skip the work of calculating it:

caps.setCapability(“derivedDataPath”, “/Users/sanojs/Library/Developer/Xcode/DerivedData/WebDriverAgent-apridxpigtzdjdecthgzpygcmdkp”);

     The last optimization is to specify the webDriverAgentUrl desired capability. If specified, Appium skips a step where it checks to make sure that there are no obsolete or abandoned WebDriverAgent processes still running. The WebDriverAgent server needs to already be running at this location, so we can only use this desired capability after the first test starts the server.

caps.setCapability(“webDriverAgentUrl”, “http://localhost:8100”);

       I hope the above tips will help you to speed up the iOS automation using Appium. Please try to change your Desired Capability today to get a better speed of automation on the iOS platform.

Refer the tips to improve the speed for Android @https://journeyofquality.wordpress.com/category/speed-up-android-appium-test-automation/

Reference: Appium Pro

make it perfect!

Automation with SeeTest Cloud

image2016-3-15 12_13_22

     From my experience with automation execution on Cloud tools, I had done the executions with Perfecto Cloud, Sauce Labs, Browserstack; now am with SeeTest Cloud. In SeeTest Cloud, easily run your Selenium and Appium tests against real iOS, Android & desktop browsers, ensuring that you are testing real user scenarios accurately.

       Start testing mobile and web applications on the cloud. It will support both manual and automation tests. Allows you to easily create automated tests for your mobile application using our large selection of real iOS and Android.

     Here I would like to share what are the capabilities required to execute your automation scripts in SeeTest Cloud for Mobile Native (iOS and Android), Mobile Web (iOS and Android) and Desktop Browsers. Before start setup the capabilities and script execution, you need a account in SeeTest Cloud. For the account, you need to register with SeeTest Cloud (https://cloud.seetest.io/) and get the access key, specify the access key in the set of test capabilities to gain access to remote testing. Once the access key ready, you can set the Desired Capabilities and instantiate the driver for Automation scripts. Following steps helps to get the access key from your registered SeeTest Cloud account,

In the cloud, click on your profile → Get Access Key

Capture.PNG

For Mobile Native - Android

AndroidDriver driver = null;
DesiredCapabilities dc = new DesiredCapabilities(); 
dc.setCapability("testName", "Android Mobile Native Test Execution"); 
dc.setCapability("accessKey", "your_SeeTest_acess_key");
dc.setCapability("deviceQuery", "@os='android'"); 
dc.setCapability("deviceModel", "device_name"); 
dc.setCapability(MobileCapabilityType.PLATFORM_VERSION, "device OS_version"); 
dc.setCapability(MobileCapabilityType.UDID, "device_UDID"); 
dc.setCapability(MobileCapabilityType.APP, "application_location_in_SeeTest"); 
dc.setCapability(AndroidMobileCapabilityType.APP_PACKAGE, "application_package_name"); 
dc.setCapability(AndroidMobileCapabilityType.APP_ACTIVITY, "application_activity_name"); 
driver = new AndroidDriver<>(new URL("https://cloud.seetest.io/wd/hub"), dc);
For Mobile Native - iOS

IOSDriver driver = null;
DesiredCapabilities dc = new DesiredCapabilities(); 
dc.setCapability("testName", "iOS Mobile Native Test Execution");
dc.setCapability("accessKey", "your_SeeTest_acess_key");
dc.setCapability("deviceQuery", "@os='ios'"); 
dc.setCapability("deviceModel", "device_name"); 
dc.setCapability(MobileCapabilityType.PLATFORM_VERSION, "device_OS_version"); 
dc.setCapability(MobileCapabilityType.UDID, "device_UDID"); 
dc.setCapability(MobileCapabilityType.APP, "application_location_in_SeeTest Cloud"); 
dc.setCapability(IOSMobileCapabilityType.BUNDLE_ID, "Bundle_ID of the application");
driver = new IOSDriver<>(new URL("https://cloud.seetest.io/wd/hub"), dc);
For Mobile Web - Android

AndroidDriver driver = null;
DesiredCapabilities dc = new DesiredCapabilities(); 
dc.setCapability("testName", "Android Mobile Web Test Execution");
dc.setCapability("accessKey", "your_SeeTest_acess_key");
dc.setCapability("deviceQuery", "@os='android'"); 
dc.setCapability("deviceModel", "device_name"); 
dc.setCapability(MobileCapabilityType.PLATFORM_VERSION, "device_OS_version"); 
dc.setCapability(MobileCapabilityType.UDID, "device_UDID"); 
dc.setBrowserName(MobileBrowserType.CHROMIUM);
driver = new AndroidDriver<>(new URL("https://cloud.seetest.io/wd/hub"), dc);
For Mobile Web- iOS

IOSDriver driver = null;
DesiredCapabilities dc = new DesiredCapabilities();
dc.setCapability("testName", "iOS Mobile Web Test Execution");
dc.setCapability("accessKey", "your_SeeTest_acess_key");
dc.setCapability("deviceQuery", "@os='ios'");
dc.setCapability("deviceModel", "device_name");
dc.setCapability(MobileCapabilityType.PLATFORM_VERSION, "selected_device_OS_version");
dc.setCapability(MobileCapabilityType.UDID, "device_UDID");
dc.setBrowserName(MobileBrowserType.SAFARI);
driver = new IOSDriver<>(new URL("https://cloud.seetest.io/wd/hub"), dc);
For Desktop Web

WebDriver driver;
DesiredCapabilities dc = new DesiredCapabilities();
dc.setCapability("testName", "Desktop Web Test Execution");
dc.setCapability("accessKey", "your_SeeTest_acess_key");
dc.setCapability(CapabilityType.PLATFORM, "desktop_OS_name"); 
dc.setCapability(CapabilityType.BROWSER_NAME, "name of the browser"); 
dc.setCapability(CapabilityType.VERSION, "browser_version");
driver = new RemoteWebDriver(new URL("https://cloud.seetest.io/wd/hub"), dc);

Now, the capabilities and driver is ready, next you can start writing your automation scripts and execute it on SeeTest Cloud.

make it perfect !

 

Browserstack supports mobile native automation

real-mobile.png

        I would like to announce that Browserstack supporting native mobile automation capability. Now you can upload the apk or iPA to browserstack server (in your browserstack account), set up the capabilities, create Android or iOS driver and start scripting.

Keep following steps in your mind:

  • Step 1: Setup Environment .
    • Ensure you have Appium Java client library and Java driver bindings installed)
  • Step 2: Upload your App.
    • Use our REST API to upload your .apk or .ipa file using CI tools.
      curl -u "browserstack_username:browserstack_accesskey" \
       -X POST "https://api.browserstack.com/app-automate/upload" \
       -F "file=@/path/to/app/file/Application-debug.apk"

      Note the app_url returned in the API response and update the app capability in your test code with it.

  • Step 3: Configure and Run test.
    • In this step you have to set the capabilities, create driver (iOS or Android) using Java class if you are using language as Java.

Following is the sample snippet,

For Android
import java.net.URL;
import java.util.List;
import java.net.MalformedURLException;
import io.appium.java_client.android.AndroidDriver;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.remote.DesiredCapabilities;
public class BrowserStack {  
  public static String userName = "your_browserstack_username";
  public static String accessKey = "your_browserstack_accesskey";
  public static void main(String args[]) throws MalformedURLException, InterruptedException {
    DesiredCapabilities caps = new DesiredCapabilities();
    caps.setCapability("device", "device_name");
    caps.setCapability("os_version", "device_os_version");
    caps.setCapability("app", "app_url");
    AndroidDriver driver = new AndroidDriver(new URL("https://"+userName+":"+accessKey+"@hub-cloud.browserstack.com/wd/hub"), caps);
}
For iOS
import java.net.URL;
import java.util.List;
import java.net.MalformedURLException;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.support.ui.ExpectedConditions;
import io.appium.java_client.MobileBy;
import io.appium.java_client.ios.IOSDriver;
import io.appium.java_client.ios.IOSElement;
public class BrowserStackIOS {
  public static String accessKey = "browserstack_key";
  public static String userName = "browserstack_username";
  public static void main(String args[]) throws MalformedURLException, InterruptedException {
    DesiredCapabilities caps = new DesiredCapabilities();
    caps.setCapability("device", "device_name");
    caps.setCapability("os_version", "device_os_version");
    caps.setCapability("app", app_url);
    IOSDriver driver = new IOSDriver(new URL("http://"+userName+":"+accessKey+"@hub-cloud.browserstack.com/wd/hub"), caps);
}
 app_url will get by calling following API,
String authString = "browserstack_username"+ ":" + "browserstack_password";
 String authStringEnc = new BASE64Encoder().encode(authString.getBytes());
 Client restClient = Client.create();
 WebResource webResource = restClient.resource("https://api.browserstack.com/app-automate/recent_apps");
 ClientResponse resp = webResource.accept("application/json").header("Authorization", "Basic " + authStringEnc) .get(ClientResponse.class);
 if (resp.getStatus() != 200) {
 System.err.println("Unable to connect to Browserstack, please try again");
 }
 JSONParser parser = new JSONParser();
 JSONArray json = (JSONArray) parser.parse(resp.getEntity(String.class));
 String app_url = null;
 String app_name = null;
 for (int i = 0; i < json.size(); i++) {
 JSONObject jsonobject = (JSONObject) json.get(i);
 app_url = (String) jsonobject.get("app_url");
}

Try to execute your scripts using Browserstack for mobile native applications.

make it perfect !

Different Driver Services in Selenium and Appium

     mobile-application-testing-with-selenium-and-appium

     As we know that the importance of Automation is increasing day-by-day. And also most of them are looking for open source tools like Selenium and Appium. In 2017, there are some modification happened in Driver instantiation for Selenium Drivers and Appium Drivers. They are commonly using DriverServices to build and start the services for different automation sessions. Here I would like to explain important Driver Services from Selenium and Appium.

For Internet Explorer:
WebDriver driver;
InternetExplorerDriverService service = new InternetExplorerDriverService.Builder().usingDriverExecutable(new File(<path to IEdriver executable>)).usingAnyFeePort().withLogFile(new File(System.getProperty(“userdir”)+”\\Logs\\Browser_logs\\InterntExplorer_”+getCurrentDateAndTime()+”.txt”)).withLogLevel(InternetExploreDriverLogLevel.DEBUG).build();
driver = new InternetExplorerDriver(service);

For Chrome:

WebDriver driver;
ChromeDriverService chromeservices = new ChromeDriverService.Builder().usingDriverExecutable(new File(<path to chromedriver executable>)).usingAnyFreePort().withLogFile(new File(System.getProperty(“userdir”)+”\\Logs\\Browser_logs\\Chrome_”+ getCurrentDateAndTime() + “.txt”)).withVerbose(true).build();
driver = new ChromeDriver(chromeservices);

For Firefox:

WebDriver driver;
FirefoxOptions options = new FirefoxOptions();
options.setLogLevel(FirefoxDriverLogLevel.DEBUG);
GeckoDriverService geckodriverservice = new GeckoDriverService.Builder().usingDriverExecutable(new File(<path to geckodriver executable>)).usingAnyFreePort().withLogFile(new File(System.getProperty(“user.dir”) + “\\Logs\\Browser_logs\\Firefox”+getCurrentDateAndTime() + “.txt”)).build();
driver = new FirefoxDriver(geckodriverservice, options);

For Edge:

WebDriver driver;
EdgeDriverService edgeservice = new EdgeDriverService.Builder().usingDriverExecutable(new File(<path to edgedriver executable>)).usingAnyFreePort().withLogFile(new File(System.getProperty(“user.dir”)+”\\Logs\\Browser_logs\\Edge_”+ getCurrentDateAndTime() + “.txt”)).build();
driver = new EdgeDriver(edgeservice);

For PhantomJS:

WebDriver driver;
Capabilities caps = new DesiredCapabilities();
((DesiredCapabilities) caps).setJavascriptEnabled(true);
((DesiredCapabilities) caps).setCapability(“takesScreenshot”, true);
PhantomJSDriverService phantomjsservice = new PhantomJSDriverService.Builder().usingPhantomJSExecutable(new File(<path to phantomjs executable>)).usingAnyFreePort().withLogFile(new File(System.getProperty(“user.dir”)+”\\Logs\\Browser_logs\\PhantomJS_”+ getCurrentDateAndTime() + “.txt”)).build();
driver = new PhantomJSDriver(phantomjsservice, caps);

For Electron Rendered Applications:

WebDriver driver;
ChromeOptions options = new ChromeOptions();
options.setBinary();
ChromeDriverService chromeservices = new ChromeDriverService.Builder().usingDriverExecutable(new File(< path to chromedriver executable>)).usingAnyFreePort().withLogFile(new File(System.getProperty(“user.dir”) +”\\Logs\\Browser_logs\\Electron_”+ getCurrentDateAndTime() + “.txt”)).withVerbose(true).build();
driver = new ChromeDriver(chromeservices, options);

For Safari:

WebDriver driver;
SafariOptions options = new SafariOptions();
options.useCleanSession(true);
driver = new SafariDriver(options);

For Appium:

WebDriver driver;
AppiumDriverLocalService driverService = AppiumDriverLocalService.buildService(new AppiumServiceBuilder()
.withAppiumJS(new File()).usingDriverExecutable(new File()).withIPAddress(“127.0.0.1″).usingPort(4723).withArgument(AndroidServerFlag.BOOTSTRAP_PORT_NUMBER,”4724″).withArgument(AndroidServerFlag.CHROME_DRIVER_PORT,”4725”).withLogFile(new File(new File( System.getProperty(“user.dir”) +”\\Appium_logs\\appiumLogs_” + getCurrentDateAndTime() + “.txt”))
.withArgument(GeneralServerFlag.LOG_NO_COLORS));
driverService.start();

For Winium (Windows Desktop Applications):

WebDriver driver;
DesktopOptions options = new DesktopOptions();
options.setApplicationPath(<path to windowsApplication>);
WiniumDriverService service = new WiniumDriverService.Builder().usingDriverExecutable(new File(< path to winiumDriver executable>)).usingPort(9999) .withLogFile(new File(System.getProperty(“user.dir”) + “\\Logs\\Windows_logs\\Win_” + getCurrentDateAndTime() + “.txt”)) .withVerbose(false).withSilent(false).buildDesktopService();
service.start();
driver = new WiniumDriver(service, options);

Try to use above mentioned Driver Services in your automation scripts.

make it perfect !

Automation for iOS 9.3.x and above

quality-jam-2017-elise-carmichael-and-corey-pyle-jumpstarting-your-test-automation-12-638

     For iOS automation, Appium relies on system frameworks provided by Apple. For iOS 9.2 and below, Apple’s only automation technology was called UIAutomation, and it ran in the context of a process called Instruments. As of iOS 10, Apple has completely removed the UIAutomation instrument, thus making it impossible for Appium to allow testing in the way it used to. Fortunately, Apple introduced a new automation technology, called XCUITest, beginning with iOS 9.3. For iOS 10 and up, this will be the only supported automation framework from Apple.

     The below Machine configuration is mandatory for running Appium automation against an iOS 9.3.x device.

  • Appium: 1.6.4 and above
  • Mac OS: OS X El Capitan 10.11 and Above
  • Xcode Version: 8.0 and Above

Setting up appium-xcuitest-driver

     This is Appiun driver for iOS using XCUITest for back-end. It has the WebDriverAgent which is a WebDriver server implementation for iOS that can be used to remote control iOS devices. It allows you to launch & kill applications, tap & scroll views or confirm view presence on a screen. This makes it a perfect tool for application end-to-end testing or general purpose device automation. It works by linking XCTest framework and calling Apple’s API to execute commands directly on a device. WebDriverAgent is developed and used at Facebook for end-to-end testing and is successfully adopted by Appium.

EXTERNAL DEPENDENCIES

     This package has a lot of external dependencies and we need to ensure that all those dependencies are installed properly to make this work. Below section explains the dependencies and its installations:

libimobiledevice [http://www.libimobiledevice.org/]

Installation  :  > brew install ideviceinstaller

carthage: [https://github.com/Carthage/Carthage]

Installation  :  > brew install carthage

mobiledevice:

Installation: brew install mobiledevice

ios-deploy: [https://github.com/phonegap/ios-deploy]

Installation :   npm install -g ios-deploy

deviceconsole:

Installation : npm install -g deviceconsole

xcpretty: [https://github.com/supermarin/xcpretty]

Installation : gem  install xcpretty

CONFIGURATION FOR REAL DEVICES

The profile can be manually associated with the project (keep in mind that this will have to be done each time the WebDriverAgent is updated).

Once you install the Appium, you will get the path node_modules/appium-xcuitest-driver/WebDriverAgentOpen WebDriverAgent.xcodeproj in Xcode and select your developmentteam for both the WebDriverAgentLib and WebDriverAgentRunner targets. This should also auto select Signing Certificate.

Selecting Signing Certificate for WebDriverAgentLib

1

Select Provisioning Profile for WebDriverAgentRnner [Select a Wildcard Development Provisioning file since this will work for all the bundle ids]

2

     Build WebDriverAgent once to verify all above steps worked. You can just build and save the xcode project [The WebDriverAgentRunner will be installed when you execute your automation script with expected capabilities] OR you can build and install the WebDriverAgentRunner on a device connected to your mac using the below command,

xcodebuild -project WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination ‘id=’

Now you are ready to start the automation using XCUITest framework for iOS 9.3.x above devices.

make it perfect !