如何在Java应用程序中以编程方式运行所有JUnit测试?

从Eclipse我可以轻松地在我的应用程序中运行所有JUnit测试。

我希望能够在没有Eclipse(或Ant或Maven或任何其他开发工具)的情况下从应用程序jar运行目标系统上的测试。

我可以看到如何从命令行运行特定的测试或套件。

我可以手动创建一个列出我的应用程序中所有测试的套件,但这似乎容易出错 – 我确信在某些时候我会创建一个测试并忘记将它添加到套件中。

Eclipse JUnit插件有一个创建测试套件的向导,但由于某种原因它没有“看到”我的测试类。 它可能正在寻找JUnit 3测试,而不是JUnit 4注释测试。

我可以编写一个工具,通过扫描源文件自动创建套件。

或者我可以编写代码,以便应用程序扫描它自己的jar文件进行测试(通过命名约定或查找@Test注释)。

似乎应该有一个更简单的方法。 我错过了什么?

根据JUnit邮件列表中最近的一个post , ClasspathSuite可以在类路径上收集和运行所有JUnit测试。 它不是您想要的,因为它是类级注释,但源是可用的,因此您可以扩展其内部发现机制。

我的上一个解决方案遇到了一个小问题。 如果我从Eclipse运行“所有测试”,他们会跑两次,因为他们运行了单独的测试和套件。 我本可以解决这个问题,但后来我意识到有一个更简单的解决方案:

package suneido; import java.io.IOException; import java.util.ArrayList; import java.util.Enumeration; import java.util.jar.JarEntry; import java.util.jar.JarFile; public class RunAllTests { public static void run(String jarfile) { String[] tests = findTests(jarfile); org.junit.runner.JUnitCore.main(tests); } private static String[] findTests(String jarfile) { ArrayList tests = new ArrayList(); try { JarFile jf = new JarFile(jarfile); for (Enumeration e = jf.entries(); e.hasMoreElements();) { String name = e.nextElement().getName(); if (name.startsWith("suneido/") && name.endsWith("Test.class") && !name.contains("$")) tests.add(name.replaceAll("/", ".") .substring(0, name.length() - 6)); } jf.close(); } catch (IOException e) { throw new RuntimeException(e); } return tests.toArray(new String[0]); } public static void main(String[] args) { run("jsuneido.jar"); } } 

基于http://burtbeckwith.com/blog/?p=52,我想出了以下内容。 它似乎运作良好。

我可以在我的代码中运行它:

 org.junit.runner.JUnitCore.main("suneido.AllTestsSuite"); 

一个弱点是它依赖于命名约定(“Test”后缀)来识别测试。 另一个弱点是jar文件的名称是硬编码的。

 package suneido; import java.io.IOException; import java.lang.reflect.Modifier; import java.util.*; import java.util.jar.JarEntry; import java.util.jar.JarFile; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.model.InitializationError; /** * Discovers all JUnit tests in a jar file and runs them in a suite. */ @RunWith(AllTestsSuite.AllTestsRunner.class) public final class AllTestsSuite { private final static String JARFILE = "jsuneido.jar"; private AllTestsSuite() { } public static class AllTestsRunner extends Suite { public AllTestsRunner(final Class clazz) throws InitializationError { super(clazz, findClasses()); } private static Class[] findClasses() { List classFiles = new ArrayList(); findClasses(classFiles); List> classes = convertToClasses(classFiles); return classes.toArray(new Class[classes.size()]); } private static void findClasses(final List classFiles) { JarFile jf; try { jf = new JarFile(JARFILE); for (Enumeration e = jf.entries(); e.hasMoreElements();) { String name = e.nextElement().getName(); if (name.startsWith("suneido/") && name.endsWith("Test.class") && !name.contains("$")) classFiles.add(name.replaceAll("/", ".") .substring(0, name.length() - 6)); } jf.close(); } catch (IOException e) { throw new RuntimeException(e); } } private static List> convertToClasses( final List classFiles) { List> classes = new ArrayList>(); for (String name : classFiles) { Class c; try { c = Class.forName(name); } catch (ClassNotFoundException e) { throw new AssertionError(e); } if (!Modifier.isAbstract(c.getModifiers())) { classes.add(c); } } return classes; } } } 

使用JUnitCore

JUnitCore是运行测试的外观。 它支持运行JUnit 4测试,JUnit 3.8.x测试和混合。 要从命令行运行测试,请运行java org.junit.runner.JUnitCore TestClass1 TestClass2 ….对于一次性测试运行,请使用静态方法runClasses(Class [])。 如果要添加特殊侦听器,请首先创建JUnitCore实例并使用它来运行测试。

我还没有尝试过这个,但最近遇到了这个博客: http : //burtbeckwith.com/blog/?p = 52

作者提供了一个发现所有junits并运行它们的类,所以如果你将它插入到你的项目中它可能提供所需的function?

希望这可以帮助。

获取Java项目并传递项目

 JUnitLaunchShortcut jUnitLaunchShortcut = new JUnitLaunchShortcut(); jUnitLaunchShortcut.launch("Pass the Java Project containing JUnits Classes", "run"); 

您也可以使用具有内置任务的ANT 。 编写ANT脚本并在目标计算机上运行它。 ANT可以创建报告作为结果。