org.xframium.device.ng.AbstractSeleniumTest.java Source code

Java tutorial

Introduction

Here is the source code for org.xframium.device.ng.AbstractSeleniumTest.java

Source

/*******************************************************************************
 * xFramium
 *
 * Copyright 2016 by Moreland Labs, Ltd. (http://www.morelandlabs.com)
 *
 * Some open source application is free software: you can redistribute 
 * it and/or modify it under the terms of the GNU General Public 
 * License as published by the Free Software Foundation, either 
 * version 3 of the License, or (at your option) any later version.
 *  
 * Some open source application is distributed in the hope that it will 
 * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *  
 * You should have received a copy of the GNU General Public License
 * along with xFramium.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
 *******************************************************************************/
/*
 * 
 */
package org.xframium.device.ng;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.ITestResult;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.xframium.artifact.ArtifactTime;
import org.xframium.artifact.ArtifactType;
import org.xframium.device.ConnectedDevice;
import org.xframium.device.DeviceManager;
import org.xframium.device.artifact.Artifact;
import org.xframium.device.artifact.ArtifactProducer;
import org.xframium.device.data.DataManager;
import org.xframium.device.factory.DeviceWebDriver;
import org.xframium.integrations.perfectoMobile.rest.PerfectoMobile;
import org.xframium.spi.Device;
import org.xframium.spi.RunDetails;

// TODO: Auto-generated Javadoc
/**
 * The Class AbstractSeleniumTest.
 */
public abstract class AbstractSeleniumTest {

    /** The log. */
    protected static Log log = LogFactory.getLog(AbstractSeleniumTest.class);

    /** The set of devices in use on this thread. */
    private static ThreadLocal<HashMap<String, ConnectedDevice>> threadDevices = new ThreadLocal<HashMap<String, ConnectedDevice>>();

    /** The test context running on this thread. */
    private static ThreadLocal<TestContext> threadContext = new ThreadLocal<TestContext>();

    /** The name of the default device **/
    private static String DEFAULT = "default";

    /**
     * The Class TestName.
     */
    protected class TestName {

        /** The test name. */
        private String testName;

        /** The full name. */
        private String fullName;

        /** The persona name. */
        private String personaName;

        private String testContext;

        private String rawName;

        public String getRawName() {
            return rawName;
        }

        public void setRawName(String rawName) {
            this.rawName = rawName;
        }

        /**
         * Gets the full name.
         *
         * @return the full name
         */
        public String getFullName() {
            return fullName;
        }

        /**
         * Sets the full name.
         *
         * @param fullName the new full name
         */
        public void setFullName(String fullName) {
            this.fullName = fullName;
        }

        /**
         * Gets the persona name.
         *
         * @return the persona name
         */
        public String getPersonaName() {
            return personaName;
        }

        /**
         * Sets the persona name.
         *
         * @param personaName the new persona name
         */
        public void setPersonaName(String personaName) {
            this.personaName = personaName;
            formatTestName();
        }

        public String getTestContext() {
            return testContext;
        }

        public void setTestContext(String testContext) {
            this.testContext = testContext;
            formatTestName();
        }

        /**
         * Instantiates a new test name.
         */
        public TestName() {
        }

        /**
         * Instantiates a new test name.
         *
         * @param testName the test name
         */
        public TestName(String testName) {
            this.testName = testName;
            formatTestName();

        }

        /**
         * Gets the test name.
         *
         * @return the test name
         */
        public String getTestName() {
            return testName;
        }

        public void setTestName(String testName) {
            this.testName = testName;
            rawName = testName;
            formatTestName();
        }

        private void formatTestName() {
            if (testName == null)
                return;
            String useTest = testName;

            if (personaName != null && !personaName.isEmpty())
                useTest = useTest + "." + personaName;

            if (testContext != null && !testContext.isEmpty())
                useTest = useTest + "[" + testContext + "]";

            this.testName = useTest;
        }

        /**
         * Gets the device.
         *
         * @return the device
         */
        public ConnectedDevice getDevice() {
            return getConnectedDevice(DEFAULT);
        }

        /* (non-Javadoc)
         * @see java.lang.Object#toString()
         */
        public String toString() {
            if (fullName != null)
                return fullName;

            if (getConnectedDevice(DEFAULT) != null) {
                if (testName != null)
                    return testName + "-->" + getConnectedDevice(DEFAULT).toString();
                else
                    return getConnectedDevice(DEFAULT).toString();

            }
            if (testName != null)
                return testName;
            else
                return "Unknown Test";
        }

        public String getKeyName() {
            return testName + (personaName != null && !personaName.isEmpty() ? "." + personaName : "");
        }
    }

    /**
     * Gets the device data.
     *
     * @return the device data
     */
    @DataProvider(name = "deviceManager", parallel = true)
    public Object[][] getDeviceData() {
        List<Device> deviceList = DeviceManager.instance().getDevices();

        return getDeviceData(deviceList);
    }

    public Object[][] getDeviceData(List<Device> deviceList) {
        int testCount = 0;
        boolean hasPersonas = false;

        if (DataManager.instance().getTests() != null && DataManager.instance().getTests().length > 0)
            testCount = deviceList.size() * DataManager.instance().getTests().length;
        else
            testCount = deviceList.size();

        if (DataManager.instance().getPersonas() != null && DataManager.instance().getPersonas().length > 0) {
            hasPersonas = true;
            testCount = testCount * DataManager.instance().getPersonas().length;
        }

        Object[][] newArray = new Object[testCount][1];

        int currentPosition = 0;

        while (currentPosition < testCount) {
            if (DataManager.instance().getTests() != null && DataManager.instance().getTests().length > 0) {
                for (int i = 0; i < DataManager.instance().getTests().length; i++) {
                    if (hasPersonas) {
                        for (int j = 0; j < DataManager.instance().getPersonas().length; j++) {
                            TestName testName = new TestName(DataManager.instance().getTests()[i]);
                            testName.setPersonaName(DataManager.instance().getPersonas()[j]);
                            newArray[currentPosition++][0] = testName;
                        }
                    } else
                        newArray[currentPosition++][0] = new TestName(DataManager.instance().getTests()[i]);
                }
            } else {
                if (hasPersonas) {
                    for (int j = 0; j < DataManager.instance().getPersonas().length; j++) {
                        TestName testName = new TestName();
                        testName.setPersonaName(DataManager.instance().getPersonas()[j]);
                        newArray[currentPosition++][0] = testName;
                    }
                } else
                    newArray[currentPosition++][0] = new TestName();
            }
        }

        return newArray;
    }

    /**
     * Adds the capabilities.
     *
     * @param dc the dc
     */
    public void addCapabilities(DesiredCapabilities dc) {

    }

    /**
     * Gets the web driver.
     *
     * @return the web driver
     */
    protected WebDriver getWebDriver() {
        if (getConnectedDevice(DEFAULT) != null) {
            return getConnectedDevice(DEFAULT).getWebDriver();
        } else
            return null;
    }

    /**
     * Gets the device.
     *
     * @return the device
     */
    protected Device getDevice() {
        if (getConnectedDevice(DEFAULT) != null)
            return getConnectedDevice(DEFAULT).getDevice();
        else
            return null;
    }

    /**
     * Before method.
     *
     * @param currentMethod the current method
     * @param testArgs the test args
     */
    @BeforeMethod
    public void beforeMethod(Method currentMethod, Object[] testArgs) {
        try {
            Thread.currentThread().setName(testArgs[0].toString());
            if (log.isInfoEnabled())
                log.info(Thread.currentThread().getName() + ": Attempting to acquire device for "
                        + currentMethod.getName());

            ConnectedDevice connectedDevice = DeviceManager.instance().getDevice(currentMethod,
                    ((TestName) testArgs[0]).getTestName(), true, ((TestName) testArgs[0]).getPersonaName());

            if (log.isInfoEnabled())
                log.info(Thread.currentThread().getName() + ": Device acquired for " + currentMethod.getName());

            if (DataManager.instance().isArtifactEnabled(ArtifactType.DEVICE_LOG))
                connectedDevice.getWebDriver().getCloud().getCloudActionProvider()
                        .enabledLogging(connectedDevice.getWebDriver());

            TestContext ctx = new TestContext();
            ctx.currentMethod = currentMethod;
            ctx.testArgs = testArgs;

            threadContext.set(ctx);

            if (connectedDevice != null) {

                putConnectedDevice(DEFAULT, connectedDevice);

                TestName testName = ((TestName) testArgs[0]);
                if (testName.getTestName() == null || testName.getTestName().isEmpty())
                    testName.setTestName(
                            currentMethod.getDeclaringClass().getSimpleName() + "." + currentMethod.getName());

                ((TestName) testArgs[0]).setFullName(testArgs[0].toString());
                Thread.currentThread().setName(testArgs[0].toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static ConnectedDevice getConnectedDevice(String name) {
        HashMap<String, ConnectedDevice> map = getDeviceMap();

        return map.get(name);
    }

    public static void registerSecondaryDeviceOnName(String name, String deviceId) {
        TestContext ctx = threadContext.get();

        if (ctx != null) {
            if (log.isInfoEnabled())
                log.info("Attempting to acquire device for " + ctx.currentMethod.getName());

            ConnectedDevice connectedDevice = DeviceManager.instance().getUnconfiguredDevice(ctx.currentMethod,
                    ((TestName) ctx.testArgs[0]).getTestName(), ((TestName) ctx.testArgs[0]).getPersonaName(),
                    deviceId);

            if (connectedDevice != null) {
                putConnectedDevice(name, connectedDevice);
            }
        }
    }

    /**
     * After method.
     *
     * @param currentMethod the current method
     * @param testArgs the test args
     * @param testResult the test result
     */
    @AfterMethod
    public void afterMethod(Method currentMethod, Object[] testArgs, ITestResult testResult) {
        HashMap<String, ConnectedDevice> map = getDevicesToCleanUp();
        threadContext.set(null);
        Iterator<String> keys = ((map != null) ? map.keySet().iterator() : null);

        if (DataManager.instance().isArtifactEnabled(ArtifactType.DEVICE_LOG))
            map.get(DEFAULT).getWebDriver().getCloud().getCloudActionProvider()
                    .disableLogging(map.get(DEFAULT).getWebDriver());

        while ((keys != null) && (keys.hasNext())) {
            String name = keys.next();
            ConnectedDevice device = map.get(name);

            cleanUpConnectedDevice(name, device, currentMethod, testArgs, testResult);
        }

        //
        // Write out the index file for all tests
        //
        try {
            if (DataManager.instance().isArtifactEnabled(ArtifactType.EXECUTION_RECORD_HTML))
                RunDetails.instance().writeHTMLIndex(DataManager.instance().getReportFolder(), false);

            if (DataManager.instance().isArtifactEnabled(ArtifactType.EXECUTION_DEFINITION))
                RunDetails.instance().writeDefinitionIndex(DataManager.instance().getReportFolder());

            DeviceManager.instance().clearAllArtifacts();
        } catch (Exception e) {
            log.error(Thread.currentThread() + ": Error flushing artifacts", e);
        }
    }

    private void cleanUpConnectedDevice(String name, ConnectedDevice device, Method currentMethod,
            Object[] testArgs, ITestResult testResult) {
        WebDriver webDriver = device.getWebDriver();
        Device currentDevice = device.getDevice();

        try {
            if (webDriver != null) {
                String runKey = ((DEFAULT.equals(name)) ? ((TestName) testArgs[0]).getTestName()
                        : ((TestName) testArgs[0]).getTestName() + "-" + name);

                File rootFolder = new File(DataManager.instance().getReportFolder(),
                        RunDetails.instance().getRootFolder());
                rootFolder.mkdirs();
                //
                // If this test failed, run through the automatic downloads for a
                // failed test
                //
                if (!testResult.isSuccess()) {
                    if (webDriver instanceof TakesScreenshot) {
                        OutputStream os = null;
                        try {
                            byte[] screenShot = ((TakesScreenshot) webDriver).getScreenshotAs(OutputType.BYTES);
                            File useFolder = new File(rootFolder, runKey);
                            File outputFile = new File(useFolder, currentDevice.getKey()
                                    + System.getProperty("file.separator") + "failure-screenshot.png");
                            outputFile.getParentFile().mkdirs();
                            os = new BufferedOutputStream(new FileOutputStream(outputFile));
                            os.write(screenShot);
                            os.flush();
                            os.close();
                        } catch (Exception e) {
                            log.error("Error taking screenshot", e);
                            try {
                                os.close();
                            } catch (Exception e2) {
                            }
                        }
                    }

                    if (DataManager.instance().getAutomaticDownloads() != null) {
                        if (webDriver instanceof ArtifactProducer) {
                            if (DataManager.instance().getReportFolder() == null)
                                DataManager.instance().setReportFolder(new File("."));

                            for (ArtifactType aType : DataManager.instance().getAutomaticDownloads()) {
                                if (aType.getTime() == ArtifactTime.ON_FAILURE) {
                                    try {
                                        Artifact currentArtifact = ((ArtifactProducer) webDriver).getArtifact(
                                                webDriver, aType, device, runKey,
                                                testResult.getStatus() == ITestResult.SUCCESS);
                                        if (currentArtifact != null)
                                            currentArtifact.writeToDisk(rootFolder);
                                    } catch (Exception e) {
                                        log.error("Error acquiring Artifacts", e);
                                    }
                                }
                            }
                        }
                    }
                }

                try {
                    webDriver.close();
                } catch (Exception e) {
                }

                if (DataManager.instance().getAutomaticDownloads() != null) {
                    if (webDriver instanceof ArtifactProducer) {
                        if (DataManager.instance().getReportFolder() == null)
                            DataManager.instance().setReportFolder(new File("."));

                        for (ArtifactType aType : DataManager.instance().getAutomaticDownloads()) {
                            if (aType.getTime() == ArtifactTime.AFTER_TEST) {
                                try {
                                    Artifact currentArtifact = ((ArtifactProducer) webDriver).getArtifact(webDriver,
                                            aType, device, runKey, testResult.getStatus() == ITestResult.SUCCESS);
                                    if (currentArtifact != null)
                                        currentArtifact.writeToDisk(rootFolder);
                                } catch (Exception e) {
                                    log.error("Error acquiring Artifacts - " + e);
                                }
                            }
                        }
                    }
                }

                try {
                    webDriver.quit();
                } catch (Exception e) {
                }
            }

            if (currentDevice != null) {
                if (webDriver instanceof DeviceWebDriver)
                    DeviceManager.instance().addRun(((DeviceWebDriver) webDriver).getPopulatedDevice(),
                            currentMethod, ((TestName) testArgs[0]).getTestName(), testResult.isSuccess(),
                            device.getPersona());
                else
                    DeviceManager.instance().addRun(currentDevice, currentMethod,
                            ((TestName) testArgs[0]).getTestName(), testResult.isSuccess(), device.getPersona());

            }
        } finally {
            if (currentDevice != null)
                DeviceManager.instance().releaseDevice(currentDevice);
        }

    }

    @AfterSuite
    public void afterSuite() {

    }

    //
    // Helpers
    //

    private static class TestContext {
        public Method currentMethod = null;
        public Object[] testArgs = null;
    }

    private static void putConnectedDevice(String name, ConnectedDevice device) {
        HashMap<String, ConnectedDevice> map = getDeviceMap();

        map.put(name, device);
    }

    private static HashMap<String, ConnectedDevice> getDeviceMap() {
        HashMap<String, ConnectedDevice> map = threadDevices.get();

        if (map == null) {
            map = new HashMap<String, ConnectedDevice>();

            threadDevices.set(map);
        }

        return map;
    }

    private HashMap<String, ConnectedDevice> getDevicesToCleanUp() {
        HashMap<String, ConnectedDevice> map = threadDevices.get();

        threadDevices.set(null);

        return map;
    }
}