edu.abreksa.BeanTest.components.Test.java Source code

Java tutorial

Introduction

Here is the source code for edu.abreksa.BeanTest.components.Test.java

Source

/*
 * Copyright (c) 2015 Andrew Breksa (abreksa4@gmail.com)
 *
 * This file is part of BeanTest.
 *
 *     BeanTest 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 2 of the License, or
 *     (at your option) any later version.
 *
 *     BeanTest 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 BeanTest.  If not, see <http://www.gnu.org/licenses/>.
 */

package edu.abreksa.BeanTest.components;

import bsh.EvalError;
import bsh.Interpreter;
import com.esotericsoftware.minlog.Log;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.IncorrectnessListener;
import com.gargoylesoftware.htmlunit.ScriptException;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HTMLParserListener;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.javascript.JavaScriptErrorListener;
import com.google.gson.annotations.Expose;
import com.thoughtworks.selenium.webdriven.WebDriverBackedSelenium;
import edu.abreksa.BeanTest.Main;
import org.apache.commons.logging.LogFactory;
import org.openqa.selenium.Proxy;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.w3c.css.sac.CSSException;
import org.w3c.css.sac.CSSParseException;
import org.w3c.css.sac.ErrorHandler;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.Timestamp;
import java.util.*;
import java.util.logging.Level;

public class Test {

    @Expose
    private Driver driver;

    //todo: fix serialization issue
    @Expose
    private BrowserVersion browserVersion = BrowserVersion.FIREFOX_24;

    public enum Driver {
        WebDriver, HTMLUnit
    }

    public static HashMap<String, Object> data = new HashMap<String, Object>();

    /**
     * The Script code.
     */
    public String scriptCode;
    /**
     * The Base url.
     */
    @Expose
    private String baseUrl = Main.url;

    /**
     * The scripts to include, in order from first to last
     */
    @Expose
    private List<String> before = new ArrayList<String>();

    /**
     * The scripts to include after
     */
    @Expose
    private List<String> after = new ArrayList<String>();

    /**
     * The Proxy.
     */
    @Expose
    public boolean proxy = false;

    /**
     * The Locators used in the test, form of key=>css selector
     */
    @Expose
    public HashMap<String, String> locators = new HashMap<String, String>();

    /**
     * The Properties used in the test, form of key=>value
     */
    @Expose
    public HashMap<String, String> properties = new HashMap<String, String>();

    /**
     * The Name.
     */
    @Expose
    public String name;

    /**
     * The Author.
     */
    @Expose
    public String author;

    /**
     * The Script location
     */
    @Expose
    public String script;

    private TestHandle testHandle;

    public static Test testLoader(String filepath) throws IOException {
        Log.debug("Loading test \"" + filepath + "\"");
        File testFile = new File(filepath);
        if (!testFile.exists()) {
            throw new FileNotFoundException("The test definition file \"" + filepath + "\" does not exist.");
        }
        Test test = Main.gson.fromJson(Main.Utils.readFile(testFile.getAbsolutePath()), Test.class);
        StringBuilder stringBuilder = new StringBuilder();
        Queue<Object> queue = new LinkedList<Object>();
        if (!Main.config.disableHelperMethods) {
            queue.add("imports(){import *;}\r\nimports();\r\n");
            //Add log methods
            queue.add("debug(string){com.esotericsoftware.minlog.Log.debug(testHandle.getName(), string);}");
            queue.add("error(string){com.esotericsoftware.minlog.Log.error(testHandle.getName(), string);}");
            queue.add("warn(string){com.esotericsoftware.minlog.Log.warn(testHandle.getName(), string);}");
            queue.add("info(string){com.esotericsoftware.minlog.Log.info(testHandle.getName(), string);}");
            queue.add("trace(string){com.esotericsoftware.minlog.Log.trace(testHandle.getName(), string);}");
            //Add (webDriver/selenium)/webClient variables
            queue.add(
                    "if(testHandle.getDriver().equals(\"WebDriver\")){webDriver = testHandle.getWebDriver();} else if(testHandle.getDriver().equals(\"HTMLUnit\")){webClient = testHandle.getWebClient();}");
        }
        //The before scripts
        for (String string : Main.config.before) {
            queue.add(new File(string));
        }
        //The test before
        for (String string : test.before) {
            queue.add(new File(string));
        }
        if (test.scriptCode != null) {
            queue.add(test.scriptCode);
        }
        //The test
        File scriptFile = new File(test.script);
        if (!scriptFile.exists()) {
            throw new FileNotFoundException("The script file \"" + test.script + "\" does not exist.");
        } else {
            queue.add(new File(scriptFile.getAbsolutePath()));
        }
        //The test after
        for (String string : test.after) {
            queue.add(new File(string));
        }
        //The after
        for (String string : Main.config.after) {
            queue.add(new File(string));
        }
        Log.debug("Queued " + Main.gson.toJson(queue));
        Log.debug("Loading " + queue.size() + " external scripts");
        for (Object object : queue) {
            if (object instanceof File) {
                if (((File) object).exists()) {
                    Log.debug("Loading external script file \"" + object + "\"");
                    stringBuilder.append("\r\n" + Main.Utils.readFile(((File) object).getAbsolutePath()));
                } else {
                    Log.warn("External script file \"" + object + "\" does not exist.");
                }
            } else if (object instanceof String) {
                stringBuilder.append("\r\n" + object);
            }
        }
        test.scriptCode = stringBuilder.toString().replace("\r\n\r\n", "\r\n");
        Log.debug("Final script \"" + test.scriptCode + "\"");
        return test;
    }

    public String getReport() {
        return testHandle.getReport();
    }

    public Object execute() throws EvalError {
        Log.info("Starting " + name + " by " + author);
        Interpreter interpreter = new Interpreter();
        this.testHandle = new TestHandle(this);
        interpreter.set("testHandle", testHandle);
        try {
            testHandle.report.result = interpreter.eval(this.scriptCode);
        } catch (Exception e) {
            testHandle.addNote(e.getMessage());
            Log.warn(e.getMessage());
        }
        testHandle.close();
        return testHandle.report.result;
    }

    public class TestHandle {
        private WebDriver webDriver;
        private Report report;
        private WebDriverBackedSelenium selenium;

        public String getDriver() {
            return driver.name();
        }

        private Driver driver = Driver.WebDriver;
        private WebClient webClient;

        public TestHandle(Test test) {
            this.report = new Report(test);
            this.driver = test.driver;
            this.initialize();
        }

        public void setData(String key, Object data) {
            Test.data.put(key, data);
        }

        public Object getData(String key) {
            Log.debug("Getting data \"" + key + "\"");
            if (Test.data.containsKey(key)) {
                return Test.data.get(key);
            }
            return null;
        }

        public WebClient getWebClient() {
            Log.debug("Getting webClient");
            if (!driver.equals(Driver.HTMLUnit)) {
                return null;
            }
            return webClient;
        }

        public String getName() {
            return name;
        }

        public void success() {
            this.report.result = true;
        }

        public void fail() throws TestFailException {
            this.report.result = false;
            throw new TestFailException(Main.Utils.getTimestamp());
        }

        public String getReport() {
            return Main.gson.toJson(report);
        }

        public void addNote(String note) {
            addNote(note, Main.Utils.getTimestamp());
        }

        public void addNote(String note, Timestamp timestamp) {
            this.report.notes.put(timestamp, note);
        }

        public String getLocator(String key) {
            Log.debug("Getting locator for \"" + key + "\"");
            if (locators.containsKey(key)) {
                return locators.get(key);
            }
            Log.warn("There was no locator present for \"" + key + "\"");
            return null;
        }

        public void log(LogLevel logLevel, String string) {
            switch (logLevel) {
            case error:
                Log.error(name, string);
                break;
            case warn:
                Log.warn(name, string);
                break;
            case info:
                Log.info(name, string);
                break;
            case debug:
                Log.debug(name, string);
                break;
            case trace:
                Log.trace(name, string);
                break;
            }
        }

        public String getProperty(String key) {
            Log.debug("Getting property \"" + key + "\"");
            if (properties.containsKey(key)) {
                return properties.get(key);
            }
            Log.warn("There was no property \"" + key + "\" present");
            return null;
        }

        public WebDriverBackedSelenium getSelenium() {
            Log.debug("Getting selenium");
            if (!driver.equals(Driver.WebDriver)) {
                return null;
            }
            return selenium;
        }

        public WebDriver getWebDriver() {
            Log.debug("Getting webDriver");
            if (!driver.equals(Driver.WebDriver)) {
                return null;
            }
            return webDriver;
        }

        private void initialize() {
            Log.trace("initilizing testHandle");
            switch (driver) {
            case WebDriver:
                if (proxy) {
                    if (Main.config.proxySupport) {
                        try {
                            String proxyString = Main.Utils.Proxies.getProxy();
                            Proxy proxy = new org.openqa.selenium.Proxy();
                            proxy.setHttpProxy(proxyString).setFtpProxy(proxyString).setSslProxy(proxyString);
                            DesiredCapabilities cap = new DesiredCapabilities();
                            cap.setCapability(CapabilityType.PROXY, proxy);
                            webDriver = new FirefoxDriver(cap);
                        } catch (Main.Utils.Proxies.NoProxyException e) {
                            Log.error(e.getMessage() + " (continuing without one)");
                            webDriver = new FirefoxDriver();
                        }
                    } else {
                        Log.warn("Proxy is required by test, no proxies provided. Continuing without proxy");
                        webDriver = new FirefoxDriver();
                    }
                } else {
                    webDriver = new FirefoxDriver();
                }
                this.selenium = new WebDriverBackedSelenium(this.webDriver, baseUrl);
                break;
            case HTMLUnit:
                if (!Main.config.enableHTMLUnitWarnings) {
                    LogFactory.getFactory().setAttribute("org.apache.commons.logging.Log",
                            "org.apache.commons.logging.impl.NoOpLog");

                    java.util.logging.Logger.getLogger("com.gargoylesoftware.htmlunit").setLevel(Level.OFF);
                    java.util.logging.Logger.getLogger("org.apache.commons.httpclient").setLevel(Level.OFF);
                }

                if (proxy) {
                    if (Main.config.proxySupport) {
                        try {
                            String proxyString = Main.Utils.Proxies.getProxy();
                            webClient = new WebClient(browserVersion, proxyString.split(":")[0],
                                    Integer.valueOf(proxyString.split(":")[1]));
                        } catch (Main.Utils.Proxies.NoProxyException e) {
                            Log.error(e.getMessage() + " (continuing without one)");
                            webClient = new WebClient(browserVersion);
                        }
                    } else {
                        Log.warn("Proxy is required by test, no proxies provided. Continuing without proxy");
                        webClient = new WebClient(browserVersion);
                    }
                } else {
                    webClient = new WebClient(browserVersion);
                }
                if (!Main.config.enableHTMLUnitWarnings) {
                    webClient.setIncorrectnessListener(new IncorrectnessListener() {

                        @Override
                        public void notify(String arg0, Object arg1) {
                            // TODO Auto-generated method stub

                        }
                    });
                    webClient.setCssErrorHandler(new ErrorHandler() {

                        @Override
                        public void warning(CSSParseException exception) throws CSSException {

                        }

                        @Override
                        public void error(CSSParseException exception) throws CSSException {

                        }

                        @Override
                        public void fatalError(CSSParseException exception) throws CSSException {

                        }
                    });
                    webClient.setJavaScriptErrorListener(new JavaScriptErrorListener() {

                        @Override
                        public void timeoutError(HtmlPage arg0, long arg1, long arg2) {
                            // TODO Auto-generated method stub

                        }

                        @Override
                        public void scriptException(HtmlPage arg0, ScriptException arg1) {
                            // TODO Auto-generated method stub

                        }

                        @Override
                        public void malformedScriptURL(HtmlPage arg0, String arg1, MalformedURLException arg2) {
                            // TODO Auto-generated method stub

                        }

                        @Override
                        public void loadScriptError(HtmlPage arg0, URL arg1, Exception arg2) {
                            // TODO Auto-generated method stub

                        }
                    });
                    webClient.setHTMLParserListener(new HTMLParserListener() {

                        @Override
                        public void error(String s, URL url, String s1, int i, int i1, String s2) {

                        }

                        @Override
                        public void warning(String s, URL url, String s1, int i, int i1, String s2) {

                        }
                    });
                }
                break;

            }

        }

        private void close() {
            switch (driver) {
            case WebDriver:
                webDriver.close();
                break;
            case HTMLUnit:
                webClient.closeAllWindows();
            }
        }

        public class TestFailException extends Exception {

            public TestFailException(Timestamp timestamp) {
                addNote("Test failed.", timestamp);
            }
        }

        public class Report {

            @Expose
            public String test;

            @Expose
            public HashMap<Timestamp, String> notes = new HashMap<Timestamp, String>();

            @Expose
            public Object result;

            public Report(Test test) {
                this.test = test.name;
            }
        }
    }

}