如何从我的 Java 应用程序内部运行 JUnit 测试?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2543912/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I run JUnit tests from inside my java application?
提问by corgrath
Is it possible to run JUnit tests from inside my java application?
是否可以从我的 Java 应用程序内部运行 JUnit 测试?
Are there test frameworks I can use (such as JUnit.jar?), or am I force to find the test files, invoke the methods and track the exceptions myself?
是否有我可以使用的测试框架(例如 JUnit.jar?),还是我必须自己查找测试文件、调用方法并跟踪异常?
The reason why I am asking is my application requires a lot of work to start launch (lots of dependencies and configurations, etc) and using an external testing tool (like JUnit Ant task) would require a lot of work to set up.
我问的原因是我的应用程序需要大量工作才能启动(大量依赖项和配置等),并且使用外部测试工具(如 JUnit Ant 任务)需要大量工作来设置。
It is easier to start the application and then inside the application run my tests.
启动应用程序然后在应用程序内部运行我的测试更容易。
Is there an easy test framework that runs tests and output results from inside a java application or am I forced to write my own framework?
是否有一个简单的测试框架可以从 Java 应用程序内部运行测试并输出结果,还是我被迫编写自己的框架?
采纳答案by kopper
Yes, you can. I was doing it couple of times to run diagnostic/smoke tests in production systems. This is a snippet of key part of the code invoking JUnit:
是的你可以。我做了几次在生产系统中运行诊断/烟雾测试。这是调用 JUnit 的代码的关键部分的片段:
JUnitCore junit = new JUnitCore();
Result result = junit.run(testClasses);
DON'T use JUnit.main
inside your application, it invokes System.exit
after tests are finished and thus it may stop JVM process.
不要JUnit.main
在你的应用程序中使用,它会System.exit
在测试完成后调用,因此它可能会停止 JVM 进程。
You may want to capture JUnit's "regular" console output (the dots and simple report). This can be easily done by registering TextListener
(this class provides this simple report).
您可能想要捕获 JUnit 的“常规”控制台输出(点和简单的报告)。这可以通过注册轻松完成TextListener
(这个类提供了这个简单的报告)。
Please also be aware of several complications using this kind of method:
还请注意使用这种方法的几个并发症:
Testing of any "test framework", including so small one, although is quite simple may be confusing. For example if you want to test if your "test framework" return failure result when one of the tests fails you could (should?) create sample JUnit test that always fails and execute that test with the "test framework". In this case failing test case is actually test data and shouldn't be executed as "normal" JUnit. For an example of such tests you can refer to JUnit's internal test cases.
If you want to prepare / display your custom report you should rather register your own
RunListener
, because Result returned by JUnit doesn't contain (directly) information about passed tests and test method (it is only "hardcoded" as a part of testDescription
).
测试任何“测试框架”,包括这么小的一个,虽然很简单可能会令人困惑。例如,如果您想在其中一个测试失败时测试您的“测试框架”是否返回失败结果,您可以(应该?)创建始终失败的示例 JUnit 测试并使用“测试框架”执行该测试。在这种情况下,失败的测试用例实际上是测试数据,不应作为“正常”JUnit 执行。有关此类测试的示例,您可以参考 JUnit 的内部测试用例。
如果你想准备/显示你的自定义报告,你应该注册你自己的
RunListener
Result ,因为 JUnit 返回的 Result 不包含(直接)关于通过的测试和测试方法的信息(它只是作为 test 的一部分“硬编码”Description
)。
回答by Tomislav Nakic-Alfirevic
回答by corgrath
According to the JUnit API, JUnitCore has several methods to execute tests inside Java.
根据 JUnit API,JUnitCore 有几种方法可以在 Java 中执行测试。
Thanks to Tomislav Nakic-Alfirevic for pointing it out.
感谢 Tomislav Nakic-Alfirevic 指出这一点。
http://junit.sourceforge.net/javadoc/org/junit/runner/JUnitCore.html
http://junit.sourceforge.net/javadoc/org/junit/runner/JUnitCore.html
回答by seanhodges
The reason why I am asking is my application requires a lot of work to start launch (lots of dependencies and configurations, etc) and using an external testing tool (like JUnit Ant task) would require a lot of work to set up.
我问的原因是我的应用程序需要大量工作才能启动(大量依赖项和配置等),并且使用外部测试工具(如 JUnit Ant 任务)需要大量工作来设置。
You need to remove these dependencies from the code you are testing. The dependencies and configurations are precisely what you are trying to avoid when writing a test framework. For each test, you should be targeting the smallest testable part of an application.
您需要从正在测试的代码中删除这些依赖项。依赖项和配置正是您在编写测试框架时要避免的。对于每个测试,您应该针对应用程序中最小的可测试部分。
For example, if you require a database connection to execute some process in a class you are trying to test - decouple the database handling object from your class, pass it in via a constructor or setter method, and in your test use a tool like JMock (or write a stub class) to build a fake database handling object. This way you are making sure the tests are not dependent on a particular database configuration, and you are only testing the small portion of code you are interested in, not the entire database handling layer as well.
例如,如果您需要一个数据库连接来执行您尝试测试的类中的某个进程 - 将数据库处理对象与您的类分离,通过构造函数或 setter 方法将其传入,并在您的测试中使用像 JMock 这样的工具(或编写一个存根类)来构建一个假的数据库处理对象。通过这种方式,您可以确保测试不依赖于特定的数据库配置,并且您只测试您感兴趣的一小部分代码,而不是整个数据库处理层。
It might seem like a lot of work at first, but this kind of refactoring is exactly what your test framework should be fleshing out. You might find it useful to get a book on software testing as a reference for decoupling your dependencies. It will pay off a lot more than trying to bootstrap JUnit from inside your running application.
乍一看似乎需要做很多工作,但这种重构正是您的测试框架应该充实的内容。您可能会发现获得一本关于软件测试的书作为解耦依赖项的参考很有用。与尝试从正在运行的应用程序内部引导 JUnit 相比,它的回报要高得多。
回答by makson
In JUnit 5 you can use Launcher APIfor this goals.
在 JUnit 5 中,您可以使用Launcher API来实现此目标。
final LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
.selectors(
selectPackage("path_to_folder_with_tests")
)
.build();
final Launcher launcher = LauncherFactory.create();
final boolean pathContainsTests = launcher.discover(request).containsTests()
if (!pathContainsTests) {
System.out.println("This path is invalid or folder doesn't consist tests");
}
final SummaryGeneratingListener listener = new SummaryGeneratingListener();
launcher.execute(request, listener);
final TestExecutionSummary summary = listener.getSummary();
final long containersFoundCount = summary.getContainersFoundCount();
System.out.println("containers Found Count " + containersFoundCount);
final long containersSkippedCount = summary.getContainersSkippedCount();
System.out.println("containers Skipped Count " + containersSkippedCount);
final long testsFoundCount = summary.getTestsFoundCount();
System.out.println("tests Found Count " + testsFoundCount);
final long testsSkippedCount = summary.getTestsSkippedCount();
System.out.println("tests Skipped Count " + testsSkippedCount);
回答by Raffi Khatchadourian
Result result = JUnitCore.runClasses(classes);
See http://junit.sourceforge.net/javadoc/org/junit/runner/JUnitCore.html#runClasses(java.lang.Class...)
见http://junit.sourceforge.net/javadoc/org/junit/runner/JUnitCore.html#runClasses(java.lang.Class...)