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

net.reini.junit.RecursiveTestSuiteBuilder Maven / Gradle / Ivy

/**
 * File Name: RecursiveTestSuiteBuilder.java
 * 
 * Copyright (c) 2014 Patrick Reinhart, All Rights Reserved.
 */

package net.reini.junit;

import java.io.File;
import java.io.FilenameFilter;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import junit.framework.JUnit4TestAdapter;
import junit.framework.TestCase;
import junit.framework.TestSuite;

/**
 * Helper class that builds test suite content based on a class file location
 * 
 * @author Patrick Reinhart
 */
public abstract class RecursiveTestSuiteBuilder {

  private static TestClassFilter _filter;

  /**
   * @return the default file name filter
   */
  public static FilenameFilter getFilenameFilter() {
    if (_filter == null) {
      _filter = new TestClassFilter();
    }
    return _filter;
  }

  /**
   * Builds all recursive test suites starting in the directories of the given
   * classInPackages
   * 
   * @param classInPackages class array used to get those packages
   * @param rootSuite the root test suite
   * @throws Exception if the the suite could not be built
   */
  public static void build(Class[] classInPackages, TestSuite rootSuite) throws Exception {
    for (Class classInPackage : classInPackages) {
      build(classInPackage, rootSuite);
    }
  }

  /**
   * Builds all recursive test suites starting in the directory of the given
   * classInPackage
   * 
   * @param classInPackage specifies a class file to get the package for
   * @param rootSuite the root test suite
   * @throws Exception if the the suite could not be built
   */
  public static void build(Class classInPackage, TestSuite rootSuite) throws Exception {
    String testSuiteClassName = classInPackage.getName();
    File suiteFile = new File(classInPackage.getClassLoader()
        .getResource(testSuiteClassName.replace('.', '/').concat(".class")).getFile());
    Package basePackage = classInPackage.getPackage();
    String basePackageName = basePackage == null ? "" : basePackage.getName();
    File baseDir = suiteFile.getParentFile();
    String suiteName = basePackageName.isEmpty() ? "[default package]" : basePackageName;
    TestSuite suite = new TestSuite(suiteName);
    rootSuite.addTest(suite);
    build(baseDir.getAbsolutePath().length(), basePackageName, baseDir, getFilenameFilter(), suite);
  }

  /**
   * Builds all recursive test suites for the given rootSuite
   * 
   * @param prefixLength the length of the prefix
   * @param basePackage the base package name
   * @param currentDir the current directory
   * @param filter a file name filter
   * @param rootSuite the root test suite
   * @throws Exception if the the suite could not be built
   */
  public static void build(int prefixLength, String basePackage, File currentDir,
      FilenameFilter filter, TestSuite rootSuite) throws Exception {
    List potentialDirectories = Arrays.asList(currentDir.listFiles(filter));
    if (!potentialDirectories.isEmpty()) {
      StringBuilder currentPackageName = new StringBuilder(200);
      currentPackageName.append(basePackage);
      String absolutePath = currentDir.getAbsolutePath();
      int startIndex = prefixLength;
      if (basePackage.isEmpty() && absolutePath.length() > prefixLength) {
        startIndex = prefixLength + 1;
      }
      String replaced = absolutePath.substring(startIndex).replaceAll("[\\\\|/]", ".");
      currentPackageName.append(replaced);
      List classFiles = new ArrayList<>(potentialDirectories.size());
      Collections.sort(potentialDirectories, new FileComparator());
      for (File potentialDirectory : potentialDirectories) {
        if (potentialDirectory.isDirectory()) {
          TestSuite subTestSuite = new TestSuite(potentialDirectory.getName());
          build(prefixLength, basePackage, potentialDirectory, filter, subTestSuite);
          // only if suite contains tests
          if (subTestSuite.countTestCases() > 0) {
            rootSuite.addTest(subTestSuite);
          }
        } else {
          classFiles.add(potentialDirectory);
        }
      }
      for (File file : classFiles) {
        final String fileName = file.getName().replaceFirst(".class$", "");
        final String className;
        if (currentPackageName.length() == 0) {
          className = fileName;
        } else {
          className = new StringBuilder(200).append(currentPackageName).append('.').append(fileName)
              .toString();
        }
        try {
          Class clazz = Class.forName(className);
          if (!Modifier.isAbstract(clazz.getModifiers())) {
            if (TestCase.class.isAssignableFrom(clazz)) {
              @SuppressWarnings("unchecked")
              Class testClass = (Class) clazz;
              rootSuite.addTestSuite(testClass);
            } else {
              rootSuite.addTest(new JUnit4TestAdapter(clazz));
            }
          }
        } catch (Throwable t) {
          Logger.getLogger(RecursiveTestSuiteBuilder.class.getName()).log(Level.SEVERE,
              "Unable to load class ".concat(className), t);
        }
      }
    }
  }

  static class TestClassFilter implements FilenameFilter {
    @Override
    public boolean accept(File dir, String name) {
      if (name.endsWith("Test.class")) {
        return true;
      }
      return new File(dir, name).isDirectory();
    }
  }

  static class FileComparator implements Comparator {
    @Override
    public int compare(File file1, File file2) {
      return file1.getAbsolutePath().compareTo(file2.getAbsolutePath());
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy