com.ecofactor.qa.automation.platform.ops.impl.AndroidOperations.java Source code

Java tutorial

Introduction

Here is the source code for com.ecofactor.qa.automation.platform.ops.impl.AndroidOperations.java

Source

/*
 * AndroidOperations.java
 * Copyright (c) 2013, EcoFactor, All Rights Reserved.
 *
 * This software is the confidential and proprietary information of EcoFactor
 * ("Confidential Information"). You shall not disclose such Confidential Information and shall use
 * it only in accordance with the terms of the license agreement you entered into with
 * EcoFactor.
 */
package com.ecofactor.qa.automation.platform.ops.impl;

import static com.ecofactor.qa.automation.platform.util.AndroidUtil.*;
import static com.ecofactor.qa.automation.platform.util.CheckJenkinsParamUtil.*;
import static com.ecofactor.qa.automation.platform.util.DeviceUtil.*;
import static com.ecofactor.qa.automation.platform.util.LogUtil.*;
import static com.ecofactor.qa.automation.platform.util.TestCaseUtil.*;
import static com.ecofactor.qa.automation.util.WaitUtil.*;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.http.conn.HttpHostConnectException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ecofactor.qa.automation.platform.SwipeableWebDriver;
import com.ecofactor.qa.automation.platform.enums.DesktopOSType;
import com.ecofactor.qa.automation.platform.enums.LogSection;
import com.ecofactor.qa.automation.platform.exception.DeviceException;
import com.ecofactor.qa.automation.platform.model.GridCapability;
import com.ecofactor.qa.automation.platform.model.GridConfiguration;
import com.ecofactor.qa.automation.platform.model.NodeConfigForGrid;
import com.ecofactor.qa.automation.platform.util.JenkinsParamUtil;
import com.ecofactor.qa.automation.platform.util.SystemUtil;
import com.ecofactor.qa.automation.util.JsonUtil;
import com.ecofactor.qa.automation.util.StringUtil;

/**
 * The Class AndroidOperations.
 * @author $Author:$
 * @version $Rev:$ $Date:$
 */
public class AndroidOperations extends AbstractMobileOperations {

    private static final String ECOFACTOR_APK = "/EcoFactor-Android/EcoFactorNew.apk";
    private static final String DEVICE_STATE = ".state";
    private static final String NATIVE_APP = "NATIVE_APP";
    private static final String WEBVIEW = "WEBVIEW";
    private static final Logger LOGGER = LoggerFactory.getLogger(AndroidOperations.class);
    private static final String DEFAULT_PORT = "4723";

    /**
     * Creates the cmd for device info.
     * @param deviceId the device id
     * @return the list
     * @see com.ecofactor.qa.automation.platform.ops.impl.AbstractMobileOperations#createCmdForDeviceInfo(java.lang.String)
     */
    @Override
    protected List<String> createCmdForDeviceInfo(final String deviceId) {

        return arrayToList("adb", "-s", deviceId, "shell", "cat", "/system/build.prop");
    }

    /**
     * Gets the device props map.
     * @param deviceId the device id
     * @param deviceVersionMap the device version map
     * @return the device props map
     * @throws DeviceException the device exception
     * @see com.ecofactor.qa.automation.mobile.ops.impl.AbstractMobileOperations#getDevicePropsMap(java.lang.String,
     *      java.util.Map)
     */
    @Override
    protected void getDevicePropsMap(final String deviceId, final Map<String, String> deviceVersionMap)
            throws DeviceException {

        if (deviceProps.get(deviceId + DEVICE_STATE).equals("unauthorized")) {
            killExistingProcess();
            getDeviceIds();
            smallWait();
        }
        if (deviceProps.get(deviceId + DEVICE_STATE).equals("Online")) {
            deviceProps.put(deviceId + ".Id", deviceId);
            updateDeviceProperties(deviceId);
            deviceVersionMap.put(deviceProps.getProperty(deviceId + ".Version"), deviceId);
        } else {
            setErrorMsg("Mobile device with ID '" + deviceId + "' is " + deviceProps.get(deviceId + DEVICE_STATE));
            hasErrors = true;
            setLogString("\033[41;1m" + getErrorMsg(), true);
            throw new DeviceException(getErrorMsg());
        }
    }

    /**
     * Update device properties.
     * @param deviceId the device id
     */
    private void updateDeviceProperties(final String deviceId) {

        final Map<String, String> propertyMap = getPropertyFromArray(getDeviceInfo(deviceId), "=");
        deviceProps.put(deviceId + ".Brand", propertyMap.get("ro.product.brand"));
        deviceProps.put(deviceId + ".Model", propertyMap.get("ro.product.model"));
        deviceProps.put(deviceId + ".Version", propertyMap.get("ro.build.version.sdk"));
        deviceProps.put(deviceId + ".OsName", getOsName(propertyMap.get("ro.build.version.sdk")));
        deviceProps.put(deviceId + ".WIFI", getWiFiConnectionState());
    }

    /**
     * Creates the device driver.
     * @return the web driver
     * @throws DeviceException the device exception
     * @see com.ecofactor.qa.automation.mobile.ops.impl.AbstractMobileOperations#createDeviceDriver()
     */
    @Override
    public WebDriver createDeviceDriver() throws DeviceException {

        return createMobileInstance(false);
    }

    /**
     * Creates the mobile instance.
     * @param deviceType the device type
     * @return the web driver
     * @throws DeviceException the device exception
     */
    private WebDriver createMobileInstance(final boolean deviceType) throws DeviceException {

        if (!hasErrors) {
            try {
                setLogString(LogSection.START, deviceType ? "Uninstalling App" : "Installing App", true);
                final File app = getAppPath();
                setLogString("App Location : " + app.getPath(), true);
                final DesiredCapabilities capabilities = setDriverCapabilities(deviceType, app);
                setLogString("Launch webdriver", true);
                final WebDriver driver = new SwipeableWebDriver(new URL(getAppiumHostUrl()), capabilities);
                setLogString(LogSection.END, "App Process Completed", true);
                return driver;
            } catch (Exception ex) {
                if (ex.getCause() instanceof HttpHostConnectException) {
                    setErrorMsg("\033[41;1mAppium not started, Please start.");
                    setLogString(LogSection.END, errorMsg, true);
                    hasErrors = true;
                    throw new DeviceException(getErrorMsg());
                }
                logInitializationError(ex);
            }
        }
        return null;
    }

    /**
     * Gets the app path.
     * @return the app path
     */
    private File getAppPath() {

        final File appDir = new File(System.getProperty("user.dir"));
        return new File(appDir, ECOFACTOR_APK);
    }

    /**
     * Sets the driver capabilities.
     * @param deviceType the device type
     * @param app the app
     * @return the desired capabilities
     */
    private DesiredCapabilities setDriverCapabilities(final boolean deviceType, final File app) {

        final DesiredCapabilities capabilities = new DesiredCapabilities();
        capabilities.setCapability("device", deviceType ? "Android" : "Selendroid");
        capabilities.setCapability("launch", deviceType ? "false" : "true");
        setHubCapabilities(capabilities);
        capabilities.setCapability("app", app.getAbsolutePath());
        capabilities.setCapability("app-package", "com.ecofactor.mobileapp.qa");
        capabilities.setCapability("app-activity", "com.ecofactor.mobileapp.qa.QA_Ecofactor");
        capabilities.setJavascriptEnabled(true);
        return capabilities;
    }

    /**
     * Perform device cleanup.
     * @throws DeviceException the device exception
     * @see com.ecofactor.qa.automation.mobile.ops.DeviceOperations#performCleanup()
     */
    @Override
    public void performCleanup() throws DeviceException {

        final WebDriver driver = createMobileInstance(true);
        if (driver != null) {
            setLogString("Quit existing driver", true);
            driver.quit();
        }
    }

    /**
     * Start Appium server.
     * @see com.ecofactor.qa.automation.mobile.ops.impl.AbstractMobileOperations#startAppiumServer()
     */
    @Override
    public void startAppiumServer() {

        setLogString(LogSection.START, "Start appium server", true);
        final String deviceId = getDeviceIdParam();
        if (!deviceProps.get(deviceId + DEVICE_STATE).equals("Online")) {
            setLogString("Appium will not be started since the device state is = "
                    + deviceProps.get(deviceId + DEVICE_STATE) + ".", true);
            return;
        }
        final String appiumHome = System.getenv("APPIUM_HOME");
        setLogString("APPIUM_HOME : " + appiumHome, true);
        if (appiumHome == null || appiumHome.isEmpty()) {
            setErrorMsg("\033[41;1mPlease set APPIUM_HOME environment variable and try again.");
            setLogString(errorMsg, true);
            hasErrors = true;
            return;
        }
        generateNodeConfig();
        final List<String> commands = arrayToList("node", ".", "-U", deviceId, "-p", DEFAULT_PORT, "--full-reset");
        String listToString = StringUtil.listToString(commands, " ");
        final int indexOfK = listToString.lastIndexOf("/k");
        listToString = listToString.substring(indexOfK + 2, listToString.length());
        setLogString("Command to Start Appium Server:" + listToString, true);

        final ProcessBuilder process = new ProcessBuilder(commands);
        process.directory(new File(appiumHome));
        process.redirectOutput(new File("outPut.txt"));
        process.redirectError(new File("error.txt"));
        startProcessBuilder(process);
        mediumWait();
        setLogString(LogSection.END, "Started appium server", true);
    }

    /**
     * Get deviceIds.
     * @return the device ids
     * @see com.ecofactor.qa.automation.mobile.ops.impl.AbstractMobileOperations#getDeviceIds()
     */
    @Override
    protected String[] getDeviceIds() {

        final String[] result = runCommands(arrayToList("adb", "devices"));
        if (result != null) {
            final List<String> resultList = arrayToList(result);
            final List<String> deviceIdList = new ArrayList<String>();
            for (final String lineValue : resultList) {
                if (!lineValue.contains("daemon") && !lineValue.contains("attached")) {
                    final String[] temp = lineValue.split("\t");
                    deviceIdList.add(temp[0].trim());
                    final String deviceState = temp[1].contains("device") ? "Online" : temp[1].trim();
                    deviceProps.put(temp[0].trim() + DEVICE_STATE, deviceState);
                }
            }
            final String[] deviceId = new String[deviceIdList.size()];
            deviceIdList.toArray(deviceId);
            return deviceId;
        }
        return null;
    }

    /**
     * Stop appium server.
     * @see com.ecofactor.qa.automation.mobile.ops.AppiumOperations#stopAppiumServer()
     */
    @Override
    public void stopAppiumServer() {

        setLogString(LogSection.START, "Stop APPIUM server if any appium session is running", true);
        final boolean isExists = isAppiumServerRunning("Stop");
        if (isExists) {
            setLogString("Stopped existing appium server", true);
        } else {
            setLogString("No Appium Server is running", true);
        }
        setLogString(LogSection.END, "Verification Completed", true);

    }

    /**
     * The main method.
     * @param args the arguments
     * @throws IOException Signals that an I/O exception has occurred.
     * @throws DeviceException the device exception
     */
    public static void main(final String[] args) throws IOException, DeviceException {

        final AndroidOperations androidOps = new AndroidOperations();
        androidOps.cleanAndStartAppium();
    }

    /**
     * Cleanup driver for close.
     * @see com.ecofactor.qa.automation.mobile.ops.impl.AbstractMobileOperations#cleanupDriverForClose()
     */
    @Override
    protected void cleanupDriverForClose() {

        // No implementation.
    }

    /**
     * Gets the device brand model.
     * @param deviceId the device id
     * @return the device brand model
     */
    public String getDeviceBrandModel(final String deviceId) {

        final Map<String, String> propertyMap = getPropertyFromArray(getDeviceInfo(deviceId), "=");
        final String brandModel = propertyMap.get("ro.product.brand") + propertyMap.get("ro.product.model");
        return brandModel;
    }

    /**
     * Verify Appium server is running.
     */
    @Override
    protected void verifyAppiumServerIsRunning() {

        setLogString("Verify Appium server is running", true);
        final boolean isRunning = isAppiumServerRunning("Start");
        setLogString("Appium server is " + (isRunning ? "" : "not ") + "running", true);
    }

    /**
     * Display app info.
     * @see com.ecofactor.qa.automation.mobile.ops.impl.AbstractMobileOperations#displayAppInfo()
     */
    @Override
    public void displayAppInfo() {

        final String[] apkInfo = runCommands(arrayToList("aapt", "d", "badging", getAppPath().getAbsolutePath()));
        final Map<String, String> propertyMap = getPropertyFromArray(apkInfo, ":");
        final String[] apk = propertyMap.get("package").split(" ");
        LOGGER.debug("Package" + apk[0] + "  " + "APK" + apk[1] + "  " + "APK" + apk[2]);
        final String apkVersionCode = apk[1].split("=")[1];
        final String apkVersion = apk[2].split("=")[1];
        System.setProperty("buildVersion", apkVersion);
        System.setProperty("buildCode", apkVersionCode);
    }

    /**
     * Switch to web view.
     * @see com.ecofactor.qa.automation.mobile.ops.DriverOperations#switchToWebView()
     */
    @Override
    public void switchToWebView() {

        getDeviceDriver().switchTo().window(WEBVIEW);
    }

    /**
     * Switch to native.
     * @see com.ecofactor.qa.automation.mobile.ops.DriverOperations#switchToNative()
     */
    @Override
    public void switchToNative() {

        getDeviceDriver().switchTo().window(NATIVE_APP);
    }

    /**
     * Generate node config json for registering Appium with the Selenium Hub.
     */
    private void generateNodeConfig() {

        final NodeConfigForGrid nodeConfig = new NodeConfigForGrid();
        nodeConfig.setCapabilities(createGridCapabilities());
        nodeConfig.setConfiguration(createGridConfig());
        JsonUtil.writeJsonToFile(nodeConfig, getNodeConfigPath());
    }

    /**
     * Gets the node config path.
     * @return the node config path
     */
    private String getNodeConfigPath() {

        return System.getProperty("user.dir") + "nodeConfig.json";
    }

    /**
     * Creates the Selenium grid capabilities.
     * @return the list
     */
    private List<GridCapability> createGridCapabilities() {

        final List<GridCapability> capabilities = new ArrayList<>();
        final GridCapability capability = new GridCapability();
        capability.setBrowserName("Android");
        capability.setMaxInstances(1);
        capability.setPlatform(DesktopOSType.WINDOWS);
        capability.setVersion(deviceProps.getProperty(getDeviceIdParam() + ".Version"));
        capabilities.add(capability);
        return capabilities;
    }

    /**
     * Creates the Selenium grid config.
     * @return the grid configuration
     */
    private GridConfiguration createGridConfig() {

        final GridConfiguration configuration = new GridConfiguration();
        configuration.setCleanUpCycle(2000);
        configuration.setTimeout(30000);
        configuration.setProxy("org.openqa.grid.selenium.proxy.DefaultRemoteProxy");
        configuration.setPort(Integer.parseInt(getMobilePortParam()));
        configuration.setMaxSession(1);
        configuration.setRegisterCycle(5000);
        configuration.setRegister(true);
        configuration.setUrl(getAppiumHostUrl());
        configuration.setHost(SystemUtil.getHostName());
        configuration.setHubHost(
                hasSeleniumHubParam() ? JenkinsParamUtil.getSeleniumHubHost() : "qwinjs11.ecofactor.com");
        configuration
                .setHubPort(hasSeleniumHubParam() ? Integer.parseInt(JenkinsParamUtil.getSeleniumHubPort()) : 4444);
        return configuration;
    }
}