All Downloads are FREE. Search and download functionalities are using the official Maven repository.

build.please.main.TestMain Maven / Gradle / Ivy

There is a newer version: 13.4.0
Show newest version
package build.please.main;

import build.please.common.report.PrettyPrintingXmlWriter;
import build.please.common.source.SourceMap;
import build.please.common.test.NotATest;
import build.please.cover.report.XmlCoverageReporter;
import build.please.cover.result.CoverageRunResult;
import build.please.cover.runner.PleaseCoverageRunner;
import build.please.test.report.XmlTestReporter;
import build.please.test.result.TestSuiteResult;
import build.please.test.runner.PleaseTestRunner;
import org.w3c.dom.Document;

import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;
import java.util.Set;

/**
 * Main class for JUnit tests which writes output to a directory.
 */
public class TestMain {
  private static final String RESULTS_DIR = "test.results";
  private static final String OUTPUT_FILE = System.getenv("COVERAGE_FILE");

  // Copied from textui.TestRunner
  private static final int SUCCESS_EXIT = 0;
  private static final int FAILURE_EXIT = 1;
  private static final int EXCEPTION_EXIT = 2;

  public static void main(String[] args) throws Exception {
    // Ensure this property matches what we are passed
    String tmpDir = System.getenv("TMP_DIR");
    if (tmpDir != null) {
      System.setProperty("java.io.tmpdir", tmpDir);
    }

    String testPackage = System.getProperty("build.please.testpackage");
    Set allClasses = findClasses(testPackage);
    if (allClasses.isEmpty()) {
      throw new RuntimeException("No test classes found");
    }

    PleaseTestRunner tester = new PleaseTestRunner(System.getProperty("PLZ_NO_OUTPUT_CAPTURE") == null, args);
    XmlTestReporter testReporter = new XmlTestReporter();

    boolean error = false;
    boolean failure = false;
    int numTests = 0;

    List testResults;
    if (System.getenv("COVERAGE") == null) {
      // plz test
      testResults = tester.runTests(allClasses);
    } else {
      // plz cover
      PleaseCoverageRunner coverage = new PleaseCoverageRunner(tester);
      XmlCoverageReporter coverageReporter = new XmlCoverageReporter();

      // This is a little bit fiddly; we want to instrument all relevant classes and then
      // once that's done run just the test classes.
      coverage.instrument(allClasses);

      String prefix = System.getProperty("build.please.instrumentationPrefix", "");
      if (!prefix.isEmpty()) {
        // User indicates that they want additional classes instrumented, which can be
        // needed in some cases so classloaders match.
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        ClassFinder finder = new ClassFinder(loader, prefix);
        coverage.instrument(finder.getClasses());
      }
      CoverageRunResult coverageRunResult = coverage.runTests(allClasses);
      testResults = coverageRunResult.testResults;

      Document coverageDoc = coverageReporter.buildDocument(coverageRunResult.coverageBuilder, coverageRunResult.testClassNames);
      PrettyPrintingXmlWriter.writeXMLDocumentToFile(OUTPUT_FILE, coverageDoc);
    }

    File dir = new File(RESULTS_DIR);
    if (!dir.exists() && !dir.mkdir()) {
      throw new IOException("Failed to create output directory: " + RESULTS_DIR);
    }

    for (TestSuiteResult result : testResults) {
      Document doc = testReporter.buildDocument(result);

      error |= result.isError();
      failure |= result.isFailure();
      numTests += result.caseResults.size();

      PrettyPrintingXmlWriter.writeXMLDocumentToFile(
          new File(RESULTS_DIR, "TEST-" + result.getClassName() + ".xml").getPath(),
          doc);
    }

    // Note that it isn't a fatal failure if there aren't any tests, unless the user specified
    // test selectors.
    if (args.length > 0 && numTests == 0) {
      throw new RuntimeException("No tests were run.");
    }

    if (error) {
      System.exit(EXCEPTION_EXIT);
    } else if (failure) {
      System.exit(FAILURE_EXIT);
    }

    System.exit(SUCCESS_EXIT);
  }

  /**
   * Constructs a URLClassLoader from the current classpath. We can't just get the classloader of the current thread
   * as its implementation is not guaranteed to be one that allows us to enumerate all the tests available to us.
   */
  private static URLClassLoader getClassLoader() throws MalformedURLException {
    String classpath = ManagementFactory.getRuntimeMXBean().getClassPath();
    String[] classpathEntries = classpath.split(":");
    // Convert from String[] to URL[]
    URL[] classpathUrls = new URL[classpathEntries.length];
    for (int i = 0; i < classpathEntries.length; i++) {
      classpathUrls[i] = new File(classpathEntries[i]).toURI().toURL();
    }
    return new URLClassLoader(classpathUrls);
  }

  /**
   * Loads all the available test classes.
   * This is a little complex because we want to try to avoid scanning every single class on our classpath.
   *
   * @param testPackage the test package to load from. If empty we'll look for them by filename.
   */
  private static Set findClasses(String testPackage) throws Exception {
    ClassLoader loader = getClassLoader();
    if (testPackage != null && !testPackage.isEmpty()) {
      return new ClassFinder(loader, testPackage).getClasses();
    }
    // Need to load by filename. Fortunately we have a list of the files we compiled in please_sourcemap.
    ClassFinder finder = new ClassFinder(loader);
    for (String key : SourceMap.readSourceMap().keySet()) {
      finder.loadClass(key.replace(".java", ".class"));
    }
    return finder.getClasses();
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy