如何在Eclipse中递归查找和运行所有Junit 4测试?

时间:2010-09-10 01:06:21

标签: eclipse junit4

我想在Eclipse项目中运行所有junit 4测试。该项目使用/ source和/ test进行设置。在/ test下是各种包,例如:

com.yaddayadda.test.core.entity
com.yaddayadda.test.core.framework

如果我在Package Explorer中右键单击/test级别并选择Run As; Junit Test我收到错误:

No tests found with test runner 'JUnit 4'.

如果我右键单击com.yaddayadda.test.core.entity,它会找到并运行该包中的所有测试。所以@Test注释是正确的(它们也在构建服务器上正确地被Ant拾取)。但是,如果我尝试在com.yaddayadda.test.core内运行所有测试,那么它就找不到。

基本上,它似乎只是在包内,而不是在所有孩子身上。有办法解决这个问题吗?

4 个答案:

答案 0 :(得分:8)

第一: 在Project Explorer中选择项目,然后按Alt + Shift + X T.它将运行项目下的所有JUint测试。通过右键单击项目并选择“运行方式” - > JUnit测试,可以完成相同的操作。

如果这不起作用(可能),请转到“运行/运行配置”,创建一个新的JUnit配置并告诉它运行项目中的所有测试。如果这不起作用,我需要先查看你的项目才能提供帮助。

答案 1 :(得分:5)

如果其他人正在寻找解决方案,我在Burt Beckwith的网站上找到了答案:

http://burtbeckwith.com/blog/?p=52

  

要使用它,只需在Eclipse的类树中右键单击它,然后单击“Run as JUnit Test”。

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Modifier;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.apache.log4j.Logger;
import org.junit.internal.runners.InitializationError;
import org.junit.runner.Description;
import org.junit.runner.RunWith;
import org.junit.runner.notification.RunListener;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.Suite;

/**
 * Discovers all JUnit tests and runs them in a suite.
 */
@RunWith(AllTests.AllTestsRunner.class)
public final class AllTests {

  private static final File CLASSES_DIR = findClassesDir();

  private AllTests() {
    // static only
  }

  /**
   * Finds and runs tests.
   */
  public static class AllTestsRunner extends Suite {

    private final Logger _log = Logger.getLogger(getClass());

    /**
     * Constructor.
     *
     * @param clazz  the suite class - <code>AllTests</code>
     * @throws InitializationError  if there's a problem
     */
    public AllTestsRunner(final Class<?> clazz) throws InitializationError {
      super(clazz, findClasses());
    }

    /**
     * {@inheritDoc}
     * @see org.junit.runners.Suite#run(org.junit.runner.notification.RunNotifier)
     */
    @Override
    public void run(final RunNotifier notifier) {
      initializeBeforeTests();

      notifier.addListener(new RunListener() {
        @Override
        public void testStarted(final Description description) {
          if (_log.isTraceEnabled()) {
            _log.trace("Before test " + description.getDisplayName());
          }
        }

        @Override
        public void testFinished(final Description description) {
          if (_log.isTraceEnabled()) {
            _log.trace("After test " + description.getDisplayName());
          }
        }
      });

      super.run(notifier);
    }

    private static Class<?>[] findClasses() {
      List<File> classFiles = new ArrayList<File>();
      findClasses(classFiles, CLASSES_DIR);
      List<Class<?>> classes = convertToClasses(classFiles, CLASSES_DIR);
      return classes.toArray(new Class[classes.size()]);
    }

    private static void initializeBeforeTests() {
      // do one-time initialization here
    }

    private static List<Class<?>> convertToClasses(
        final List<File> classFiles, final File classesDir) {

      List<Class<?>> classes = new ArrayList<Class<?>>();
      for (File file : classFiles) {
        if (!file.getName().endsWith("Test.class")) {
          continue;
        }
        String name = file.getPath().substring(classesDir.getPath().length() + 1)
          .replace('/', '.')
          .replace('\\', '.');
        name = name.substring(0, name.length() - 6);
        Class<?> c;
        try {
          c = Class.forName(name);
        }
        catch (ClassNotFoundException e) {
          throw new AssertionError(e);
        }
        if (!Modifier.isAbstract(c.getModifiers())) {
          classes.add(c);
        }
      }

      // sort so we have the same order as Ant
      Collections.sort(classes, new Comparator<Class<?>>() {
        public int compare(final Class<?> c1, final Class<?> c2) {
          return c1.getName().compareTo(c2.getName());
        }
      });

      return classes;
    }

    private static void findClasses(final List<File> classFiles, final File dir) {
      for (File file : dir.listFiles()) {
        if (file.isDirectory()) {
          findClasses(classFiles, file);
        }
        else if (file.getName().toLowerCase().endsWith(".class")) {
          classFiles.add(file);
        }
      }
    }
  }

  private static File findClassesDir() {
    try {
      String path = AllTests.class.getProtectionDomain()
        .getCodeSource().getLocation().getFile();
      return new File(URLDecoder.decode(path, "UTF-8"));
    }
    catch (UnsupportedEncodingException impossible) {
      // using default encoding, has to exist
      throw new AssertionError(impossible);
    }
  }
}

答案 2 :(得分:1)

我发现Burt Beckwith的代码很棒,但无论你在哪里放置AllTests,它都会在项目中运行每一个测试。对一个函数的这种修改将允许您将AllTests放在项目的任何子目录中,它只会在该位置下运行测试。

private static Class<?>[] findClasses() {List<File> classFiles = new ArrayList<File>();
  String packagepath = AllTests.class.getPackage().getName().replace(".", "/");
  File RELATIVE_DIR = new File( CLASSES_DIR.getAbsolutePath() + "\\" + packagepath );
  findClasses(classFiles, RELATIVE_DIR);
  List<Class<?>> classes = convertToClasses(classFiles, CLASSES_DIR);
  return classes.toArray(new Class[classes.size()]);
}

答案 3 :(得分:0)

您是否在构建路径中添加了/test - &gt;源文件夹?