58

Is it possible to run JUnit tests from inside my Java application?

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?

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 a JUnit Ant task) would require a lot of work to set up.

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?

How do I run JUnit tests from inside my Java application?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
corgrath
  • 11,673
  • 15
  • 68
  • 99
  • You can mock your resources or whatever, running test in java application makes no sense to me .. take a look at the jmock.org – ant Mar 30 '10 at 08:59

6 Answers6

92

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:

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.

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).

Please also be aware of several complications using this kind of method:

  1. 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.

  2. 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 test Description).

kopper
  • 2,676
  • 1
  • 16
  • 17
  • 1
    This is awesome. I'm trying to get an automated JUnit test suite to be run on a custom web server, so I can set up some cronjobs to launch unit tests and report back on the results nightly; this is exactly what I had hoped to find. – Shotgun Ninja May 01 '15 at 20:55
  • 3
    Following is the code to start JUnit in your main and have the basic output in the standard output: `JUnitCore junitCore = new JUnitCore(); junit.addListener(new TextListener(System.out)); junit.run(.class);` Sorry for the format, but it is the best I can do in a comment. :) – RobMcZag Apr 12 '16 at 15:44
  • This won't allow me to just run the tests in the src/test/java folder, right? you are inferring that I should migrate the tests to src/main/test and lose JUnit functionalities, correct? – White_King Jan 26 '23 at 08:42
16

As documented in the JUnit FAQ:

public static void main(String args[]) {
  org.junit.runner.JUnitCore.main("junitfaq.SimpleTest");
}
Tomislav Nakic-Alfirevic
  • 10,017
  • 5
  • 38
  • 51
  • This won't allow me to just run the tests in the src/test/java folder, right? you are inferring that I should migrate the tests to src/main/test and lose JUnit functionalities, correct? – White_King Jan 26 '23 at 08:47
  • Reasonable question. I don't know for sure, it's been a while, but it seems like several people found the answer useful over the years, so I would assume you don't need to migrate the code to src/main/test. Maybe you could confirm or disprove? – Tomislav Nakic-Alfirevic Jan 27 '23 at 10:33
  • 1
    I found out that with maven you can compile the tests to the same folder than the rest of the code and this will allow it to actually find the test. Thank you! – White_King Jan 28 '23 at 15:53
  • 1
    Thanks for trying it out and bringing back the news! – Tomislav Nakic-Alfirevic Jan 29 '23 at 17:20
10

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.

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.

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.

seanhodges
  • 17,426
  • 15
  • 71
  • 93
5

In JUnit 5 you can use Launcher API for this goals.

    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);
makson
  • 1,975
  • 3
  • 23
  • 31
  • This won't allow me to just run the tests in the src/test/java folder, right? you are inferring that I should migrate the tests to src/main/test and lose JUnit functionalities, correct? – White_King Jan 26 '23 at 08:48
2

According to the JUnit API, JUnitCore has several methods to execute tests inside Java.

Thanks to Tomislav Nakic-Alfirevic for pointing it out.

http://junit.sourceforge.net/javadoc/org/junit/runner/JUnitCore.html

corgrath
  • 11,673
  • 15
  • 68
  • 99
0
Result result = JUnitCore.runClasses(classes);

See http://junit.sourceforge.net/javadoc/org/junit/runner/JUnitCore.html#runClasses(java.lang.Class...)

Raffi Khatchadourian
  • 3,042
  • 3
  • 31
  • 37