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

org.pantsbuild.tools.junit.impl.Util Maven / Gradle / Ivy

Go to download

A command line tool for running junit tests that provides functionality above and beyond that provided by org.junit.runner.JUnitCore.

There is a newer version: 1.0.30
Show newest version
// Copyright 2015 Pants project contributors (see CONTRIBUTORS.md).
// Licensed under the Apache License, Version 2.0 (see LICENSE).

package org.pantsbuild.tools.junit.impl;

import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import org.junit.Ignore;
import org.junit.runner.Description;
import org.junit.runner.RunWith;
import org.junit.runner.notification.Failure;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;

/**
 * Utilities for working with junit test runs.
 */
final class Util {

  static final Predicate IS_ANNOTATED_TEST_METHOD =
      new Predicate() {
        @Override public boolean apply(Method method) {
          return Modifier.isPublic(method.getModifiers())
              && method.isAnnotationPresent(org.junit.Test.class);
        }
      };

  static final Predicate> IS_PUBLIC_CONSTRUCTOR =
      new Predicate>() {
        @Override public boolean apply(Constructor constructor) {
          return Modifier.isPublic(constructor.getModifiers());
        }
      };

  private Util() {
    // utility
  }

  /**
   * Returns {@code true} if the given {@code test} is {@literal @Ignore}d.
   *
   * @param test The test description to evaluate.
   * @return {@code true} if the described test is marked as ignored.
   */
  static boolean isIgnored(Description test) {
    return test.getAnnotation(Ignore.class) != null;
  }

  /**
   * Returns {@code true} if the given class is {@literal @Ignore}d
   *
   * @param clazz class instance to evaluate.
   * @return {@code true} if the class is marked as ignored.
   */
  static boolean isIgnored(Class clazz) {
    return clazz.isAnnotationPresent(Ignore.class);
  }

  /**
   * Returns {@code true} if the given {@code test} is eligible for running.  Runnable tests are
   * those that are not {@literal @Ignore}d and have direct executable content (i.e.: not a test
   * suite or other executable test aggregator).
   *
   * @param test The test description to evaluate.
   * @return {@code true} if the described test will be run by a standard junit runner.
   */
  static boolean isRunnable(Description test) {
    return test.isTest() && !isIgnored(test);
  }

  /**
   * Returns {@code false} if the given class is {@literal @Ignore}d
   *
   * @param clazz class instance to evaluate.
   * @return {@code true} if the class is marked as ignored.
   */
  static boolean isRunnable(Class clazz) {
    return isTestClass(clazz) && !isIgnored(clazz);
  }

  /**
   * Returns {@code true} if the test failure represents an assertion failure.
   *
   * @param failure The failure to test.
   * @return {@code true} if the failure was from an incorrect assertion, {@code false} otherwise.
   */
  static boolean isAssertionFailure(Failure failure) {
    return failure.getException() instanceof AssertionError;
  }

  /**
   * Returns a pants-friendly formatted description of the test-case.
   *
   * Pants likes test-cases formatted as org.foo.bar.TestClassName#testMethodName
   *
   * @param description The test description to produce a formatted name for.
   * @return The formatted name of the test-case, if possible. If the Description does not have a
   * class name or a method name, falls back on the description.getDisplayName().
   */
  static String getPantsFriendlyDisplayName(Description description) {
    String className = description.getClassName();
    String methodName = description.getMethodName();
    String vanillaDisplayName = description.getDisplayName();
    if (className.equals(vanillaDisplayName) || methodName.equals(vanillaDisplayName)) {
      // This happens if the Description isn't actually describing a test method. We don't handle
      // this, so just use the default formatting.
      return vanillaDisplayName;
    }

    StringBuffer sb = new StringBuffer(className.length() + methodName.length() + 1);
    sb.append(className);
    sb.append("#");
    sb.append(methodName);
    return sb.toString();
  }

  /**
   * Returns a sanitized suite name suitable for inclusion in a XML report.
   *
   * This is also used to generate an XML report's filename, so it is important that it does not
   * contain special characters that are illegal on the filesystem.
   *
   * This strips out punction and whitespace, but leaves the '_', '.', and '-' symbols, and trailing
   * periods are trimmed.
   *
   * @param name The name to sanitize. In most cases this is the class name of the test being run,
   *   but some frameworks (I'm looking at you, Cucumber) like to pass weird things like
   *   human-readable free-form textual descriptions of the tests, so we can't make assumptions.
   * @return
   */
  static String sanitizeSuiteName(String name) {
    return name.replaceAll("[[\\p{Punct}][\\p{Space}]&&[^_.-]]", "-").replaceAll("[.]+$", "");
  }

  /**
   * Support junit 3.x Test hierarchy.
   */
  public static boolean isJunit3Test(Class clazz) {
    return junit.framework.Test.class.isAssignableFrom(clazz);
  }

  /**
   * Support classes using junit 4.x custom runners.
   */
  public static boolean isUsingCustomRunner(Class clazz) {
    return clazz.isAnnotationPresent(RunWith.class);
  }

  public static boolean isTestClass(final Class clazz) {
    // Must be a public concrete class to be a runnable junit Test.
    if (clazz.isInterface()
        || Modifier.isAbstract(clazz.getModifiers())
        || !Modifier.isPublic(clazz.getModifiers())) {
      return false;
    }

    // The class must have some public constructor to be instantiated by the runner being used
    if (!Iterables.any(Arrays.asList(clazz.getConstructors()), IS_PUBLIC_CONSTRUCTOR)) {
      return false;
    }

    if (isJunit3Test(clazz)) {
      return true;
    }

    // Support classes using junit 4.x custom runners.
    if (isUsingCustomRunner(clazz)) {
      return true;
    }

    if (ScalaTestUtil.isScalaTestTest(clazz)) {
      return true;
    }

    // Support junit 4.x @Test annotated methods.
    return Iterables.any(Arrays.asList(clazz.getMethods()), IS_ANNOTATED_TEST_METHOD);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy