Package net.jangaroo.jooc.mvnplugin.test

Source Code of net.jangaroo.jooc.mvnplugin.test.JooTestMojo

package net.jangaroo.jooc.mvnplugin.test;

import com.thoughtworks.selenium.DefaultSelenium;
import com.thoughtworks.selenium.Selenium;
import com.thoughtworks.selenium.SeleniumException;
import org.apache.commons.io.FileUtils;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.codehaus.plexus.util.cli.CommandLineException;
import org.eclipse.jetty.server.Server;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;

/**
* Executes JooUnit tests.
* Unpacks all dependency to its output directory, generates a tests.html which starts up the class
* <code>testSuiteName</code>. Since a real browser is the best JavaScript execution environment
* the test now fires up a jetty on a random port between <code>jooUnitJettyPortLowerBound</code> and
* <code>jooUnitJettyPortUpperBound</code> contacts a selenium server given by
* <code>jooUnitSeleniumRCHost</code>. The Selenium Remote Control then starts a browser, navigates
* the browser to the Jetty we just started and waits for <code>jooUnitTestExecutionTimeout</code>ms
* for the results to appear on the browser screen.
*
* @goal test
* @phase test
* @requiresDependencyResolution test
* @threadSafe
*/
public class JooTestMojo extends JooTestMojoBase {

  /**
   * Source directory to scan for files to compile.
   *
   * @parameter expression="${project.build.testSourceDirectory}"
   */
  @SuppressWarnings({"UnusedDeclaration", "FieldCanBeLocal"})
  private File testSourceDirectory;
  /**
   * Set this to 'true' to bypass unit tests entirely. Its use is NOT RECOMMENDED, especially if you
   * enable it using the "maven.test.skip" property, because maven.test.skip disables both running the
   * tests and compiling the tests. Consider using the skipTests parameter instead.
   *
   * @parameter expression="${maven.test.skip}"
   */
  private boolean skip;
  /**
   * Set this to 'true' to skip running tests, but still compile them. Its use is NOT RECOMMENDED, but quite
   * convenient on occasion.
   *
   * @parameter expression="${skipTests}"
   */
  private boolean skipTests;

  /**
   * Output directory for test results.
   *
   * @parameter expression="${project.build.directory}/surefire-reports/"  default-value="${project.build.directory}/surefire-reports/"
   * @required
   */
  @SuppressWarnings({"UnusedDeclaration"})
  private File testResultOutputDirectory;

  /**
   * @parameter
   */
  @SuppressWarnings({"UnusedDeclaration"})
  private String testResultFileName;

  /**
   * Specifies the time in milliseconds to wait for the test results in the browser. Default is 30000ms.
   *
   * @parameter
   */
  @SuppressWarnings("FieldCanBeLocal")
  private int jooUnitTestExecutionTimeout = 30000;

  /**
   * Specifies the number of retries when receiving unexpected result from phantomjs (crash?).
   * Default is 5.
   *
   * @parameter
   */
  @SuppressWarnings("FieldCanBeLocal")
  private int jooUnitMaxRetriesOnCrashes = 5;

  /**
   * Defines the Selenium RC host. Default is localhost.
   * If the system property SELENIUM_RC_HOST is set, it is used prior to the
   * maven parameter.
   *
   * @parameter
   */
  private String jooUnitSeleniumRCHost = "localhost";

  /**
   * Defines the Selenium RC port. Default is 4444.
   *
   * @parameter
   */
  @SuppressWarnings({"UnusedDeclaration", "FieldCanBeLocal"})
  private int jooUnitSeleniumRCPort = 4444;

  /**
   * Selenium browser start command. Default is *firefox
   *
   * @parameter
   */
  @SuppressWarnings({"UnusedDeclaration", "FieldCanBeLocal"})
  private String jooUnitSeleniumBrowserStartCommand = "*firefox";

  /**
   * Set this to true to ignore a failure during testing. Its use is NOT RECOMMENDED, but quite convenient on
   * occasion.
   *
   * @parameter expression="${maven.test.failure.ignore}"
   */
  private boolean testFailureIgnore;

  /**
   * The phantomjs executable. If not specified, it expects the phantomjs binary in the PATH.
   * If not phantomjs executable (or an outdated one) is found, falls back to Selenium.
   *
   * @parameter expression="${phantomjs.bin}" default-value="phantomjs"
   */
  @SuppressWarnings({"UnusedDeclaration", "FieldCanBeLocal"})
  private String phantomBin;

  public void execute() throws MojoExecutionException, MojoFailureException {
    if (!skip && !skipTests && isTestAvailable()) {
      Server server = jettyRunTest(true);
      String url = getTestUrl(server);

      try {
        File testResultOutputFile = new File(testResultOutputDirectory, getTestResultFileName());
        File phantomTestRunner = new File(testResultOutputDirectory, "phantomjs-joounit-page-runner.js");
        FileUtils.copyInputStreamToFile(getClass().getResourceAsStream("/net/jangaroo/jooc/mvnplugin/phantomjs-joounit-page-runner.js"), phantomTestRunner);
        final PhantomJsTestRunner phantomJsTestRunner = new PhantomJsTestRunner(phantomBin, url, testResultOutputFile.getPath(), phantomTestRunner.getPath(), jooUnitTestExecutionTimeout, jooUnitMaxRetriesOnCrashes, getLog());
        if (phantomJsTestRunner.canRun()) {
          executePhantomJs(testResultOutputFile, phantomJsTestRunner);
        } else {
          executeSelenium(url);
        }
      } catch (IOException e) {
        throw new MojoExecutionException("Cannot create local copy of phantomjs-joounit-page-runner.js", e);
      } finally {
        try {
          server.stop();
        } catch (Exception e) {
          // never mind we just couldn't step the selenium server.
          getLog().error("Could not stop test Jetty.", e);
        }
      }
    }
  }

  private void executePhantomJs(File testResultOutputFile, PhantomJsTestRunner phantomJsTestRunner) throws MojoFailureException, MojoExecutionException {
    getLog().info("running phantomjs: " + phantomJsTestRunner.toString());
    try {
      final boolean exitCode = phantomJsTestRunner.execute();
      if (exitCode) {
        evalTestOutput(new FileReader(testResultOutputFile));
      } else {
        signalError();
      }
    } catch (CommandLineException e) {
      throw wrap(e);
    } catch (IOException e) {
      throw wrap(e);
    } catch (ParserConfigurationException e) {
      throw wrap(e);
    } catch (SAXException e) {
      throw wrap(e);
    }
  }

  void executeSelenium(String testsHtmlUrl) throws MojoExecutionException, MojoFailureException {
    jooUnitSeleniumRCHost = System.getProperty("SELENIUM_RC_HOST", jooUnitSeleniumRCHost);
    try {
      //check wether the host is reachable
      //noinspection ResultOfMethodCallIgnored
      InetAddress.getAllByName(jooUnitSeleniumRCHost);
    } catch (UnknownHostException e) {
      throw new MojoExecutionException("Cannot resolve host " + jooUnitSeleniumRCHost +
              ". Please specify a host running the selenium remote control or skip tests" +
              " by -DskipTests", e);
    }
    getLog().info("JooTest report directory: " + testResultOutputDirectory.getAbsolutePath());
    Selenium selenium = new DefaultSelenium(jooUnitSeleniumRCHost, jooUnitSeleniumRCPort, jooUnitSeleniumBrowserStartCommand, testsHtmlUrl);
    try {
      selenium.start();
      getLog().debug("Opening " + testsHtmlUrl);
      selenium.open(testsHtmlUrl);
      getLog().debug("Waiting for test results for " + jooUnitTestExecutionTimeout + "ms ...");
      selenium.waitForCondition("selenium.browserbot.getCurrentWindow().result != null || selenium.browserbot.getCurrentWindow().classLoadingError != null", "" + jooUnitTestExecutionTimeout);
      String classLoadingError = selenium.getEval("selenium.browserbot.getCurrentWindow().classLoadingError");
      if (classLoadingError != null && !classLoadingError.equals("null")) {
        throw new MojoExecutionException(classLoadingError);
      }

      String testResultXml = selenium.getEval("selenium.browserbot.getCurrentWindow().result");
      writeResultToFile(testResultXml);
      evalTestOutput(new StringReader(testResultXml));
    } catch (IOException e) {
      throw new MojoExecutionException("Cannot write test results to file", e);
    } catch (ParserConfigurationException e) {
      throw new MojoExecutionException("Cannot create a simple XML Builder", e);
    } catch (SAXException e) {
      throw new MojoExecutionException("Cannot parse test result", e);
    } catch (SeleniumException e) {
      throw new MojoExecutionException("Selenium setup exception", e);
    } finally {
      selenium.stop();
    }
  }

  File writeResultToFile(java.lang.String testResultXml) throws IOException {
    File result = new File(testResultOutputDirectory, getTestResultFileName());
    FileUtils.writeStringToFile(result, testResultXml);
    if (!result.setLastModified(System.currentTimeMillis())) {
      getLog().warn("could not set modification time of file " + result);
    }
    return result;
  }

  private String getTestResultFileName() {
    return testResultFileName != null ? testResultFileName : "TEST-" + project.getArtifactId() + ".xml";
  }

  void evalTestOutput(Reader inStream) throws ParserConfigurationException, IOException, SAXException, MojoFailureException {
    DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder dBuilder = documentBuilderFactory.newDocumentBuilder();
    InputSource inSource = new InputSource(inStream);
    Document d = dBuilder.parse(inSource);
    NodeList nl = d.getChildNodes();
    NamedNodeMap namedNodeMap = nl.item(0).getAttributes();
    final String failures = namedNodeMap.getNamedItem("failures").getNodeValue();
    final String errors = namedNodeMap.getNamedItem("errors").getNodeValue();
    final String tests = namedNodeMap.getNamedItem("tests").getNodeValue();
    final String time = namedNodeMap.getNamedItem("time").getNodeValue();
    final String name = namedNodeMap.getNamedItem("name").getNodeValue();
    getLog().info(name + " tests run: " + tests + ", Failures: " + failures + ", Errors: " + errors + ", time: " + time + " ms");
    if (Integer.parseInt(errors) > 0 || Integer.parseInt(failures) > 0) {
      signalFailure();
    }
  }

  private void signalError() throws MojoExecutionException {
    throw new MojoExecutionException("There are errors");
  }

  private void signalFailure() throws MojoFailureException {
    if (!testFailureIgnore) {
      throw new MojoFailureException("There are test failures");
    }
  }

  public void setSkip(boolean b) {
    this.skip = b;
  }

  public void setSkipTests(boolean b) {
    this.skipTests = b;
  }

  public void setTestSourceDirectory(File f) {
    this.testSourceDirectory = f;
  }

  public void setTestResources(ArrayList<org.apache.maven.model.Resource> resources) {
    this.testResources = resources;
  }

  public void setTestFailureIgnore(boolean b) {
    this.testFailureIgnore = b;
  }

  public void setTestOutputDirectory(File testOutputDirectory) {
    this.testOutputDirectory = testOutputDirectory;
  }
}
TOP

Related Classes of net.jangaroo.jooc.mvnplugin.test.JooTestMojo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.