Open In App

Running JUnit Tests Programmatically, from a Java Application

Last Updated : 18 Oct, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

JUnit is a popular testing framework in the Java ecosystem that enables developers to create and run tests efficiently. While it is common to run tests through IDEs or build tools, running them programmatically allows greater flexibility in integrating testing into various stages of the application execution, such as during development, automated workflows, or even in production environments. This article covers how to run JUnit tests programmatically using the JUnit Platform API.

Prerequisites

  • Basic knowledge of the Java and JUnit Framework.
  • Maven for building dependency management.
  • JDK and IntelliJ IDEA installed in your system.

Programmatically Run JUnit Tests from a Java Application

Understanding JUnit

JUnit is structured around a few key components:

  • Annotations: JUnit uses annotations to identify test methods and define the test lifecycle. For example, @Test indicates a test method, while @BeforeEach and @AfterEach are used for setup and teardown logic, respectively.
  • Assertions: Assertions are methods that check whether a specific condition is true. If the condition is false, JUnit marks the test as failed. Common assertions include assertEquals(), assertTrue(), and assertNotNull().
  • Test Suites: A test suite groups multiple test classes to be run together. This is useful for running a specific set of tests without executing all tests in the project.

JUnit Platform

JUnit 5 introduced a modular architecture known as the JUnit Platform. It consists of three main components:

  1. JUnit Jupiter: Provides the new programming model for writing tests and extensions, offering annotations, assertions, and a rich API to define tests.
  2. JUnit Vintage: Allows the execution of JUnit 3 and 4 tests on the JUnit 5 platform, providing backward compatibility.
  3. JUnit Platform: The foundation for launching testing frameworks on the JVM, providing a console launcher and the ability to run tests in different environments, including IDEs and build tools.

Running JUnit Tests Programmatically

Running JUnit tests programmatically is facilitated by the JUnit Platform Launcher API, which allows you to discover and execute tests flexibly. Here's a breakdown of how to run tests programmatically:

  1. Creating the Launcher: The Launcher interface is the primary entry point for running tests. It is created using LauncherFactory.create().
  2. Discovery Request: The LauncherDiscoveryRequest is used to define what tests to run. You can select specific classes, packages, or custom conditions using selectors. For example, DiscoverySelectors.selectPackage("com.gfg") selects all tests in the specified package.
  3. Execution: Once the discovery request is set up, calling launcher.execute(request) runs the selected tests. Additional configurations or listeners can be passed at this stage.
  4. Listeners: Listeners allow you to capture and respond to test execution events. SummaryGeneratingListener captures the outcome of the tests, enabling you to print a summary of the results.

Implementation to Run JUnit Tests Programmatically from a Java Application

This example demonstrates how to run JUnit tests programmatically in a Java application.

Step 1: Create a new Maven Project

Create a new Maven project using IntelliJ IDEA:

  • Name: junit-programmatic-tests
  • Build System: Maven

Click on the Create button.

Project Metadata

Project Structure

After the project creation done, the folder structure will look like the below image:

Project Folder Structure

Step 2: Add JUnit 5 Dependencies to pom.xml

Add the following dependencies to your Maven pom.xml file to include JUnit 5 and its components.

XML
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.gfg</groupId>
    <artifactId>junit-programmatic-tests</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <!-- JUnit 5 API -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.10.0</version>
        </dependency>

        <!-- JUnit 5 Engine for running tests -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.10.0</version>
        </dependency>

        <!-- JUnit Platform Launcher -->
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-launcher</artifactId>
            <version>1.10.0</version>
        </dependency>

        <!-- JUnit Platform Commons for utility classes -->
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-commons</artifactId>
            <version>1.10.0</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <!-- Maven Compiler Plugin to ensure Java version compatibility -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.10.1</version>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                </configuration>
            </plugin>

            <!-- Maven Exec Plugin for running the Java main class -->
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>3.0.0</version>
                <configuration>
                    <mainClass>com.example.JUnitTestRunner</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
  • JUnit Dependencies: We include junit-jupiter-api, junit-jupiter-engine, and junit-platform-launcher for creating and running tests programmatically.
  • Exec Plugin: Configures Maven to run our main class JUnitTestRunner.

Step 3: JUnitTestRunner.java

This is the main class that runs the tests programmatically using the JUnit Launcher API.

Java
package com.gfg;

import org.junit.platform.launcher.Launcher;
import org.junit.platform.launcher.LauncherDiscoveryRequest;
import org.junit.platform.launcher.core.LauncherFactory;
import org.junit.platform.launcher.listeners.SummaryGeneratingListener;
import org.junit.platform.engine.discovery.DiscoverySelectors;

import java.io.PrintWriter;

import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request;

public class JUnitTestRunner {

    public static void main(String[] args) {
        // Create a Launcher to execute tests
        Launcher launcher = LauncherFactory.create();

        // Listener to generate test execution summary
        SummaryGeneratingListener listener = new SummaryGeneratingListener();

        // Create a request to select all test classes in the "com.gfg" package
        LauncherDiscoveryRequest request = request()
                .selectors(DiscoverySelectors.selectPackage("com.gfg"))
                .build();

        // Execute the tests
        launcher.execute(request, listener);

        // Print the test results summary to the console
        try (PrintWriter writer = new PrintWriter(System.out)) {
            listener.getSummary().printTo(writer);
        }
    }
}
  • Launcher: The entry point for running the tests.
  • SummaryGeneratingListener: Captures test execution events and stores the result summary.
  • DiscoverySelectors: We use selectPackage to run all test classes in the com.gfg package.
  • PrintWriter: Prints the test summary to the console.

Step 4: SampleTest.java

This is the test class that contains sample test methods.

Java
package com.gfg;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public class SampleTest {

    // Test for addition
    @Test
    public void testAddition() {
        Assertions.assertEquals(5, 2 + 3);
    }

    // Test for subtraction
    @Test
    public void testSubtraction() {
        Assertions.assertEquals(1, 3 - 2);
    }
}
  • testAddition: This test checks if 2 + 3 equals 5.
  • testSubtraction: This test checks if 3 - 2 equals 1.

Step 5: Running the Test Runner

We can execute the JUnitTestRunner class by running the following command:

mvn exec:java -Dexec.mainClass="com.gfg.JUnitTestRunner"

Output:

JUnitTestRunner Output

Step 6: Running the Tests

We can also run the test suite using the Maven command:

mvn test

Output:

Console Output

This example project demonstrates how to set up the basic Maven project to run the JUnit tests programmatically. This structure includes the test class with sample tests and a runner that utilizes the JUnit platform API to discover and execute those tests.


Next Article
Article Tags :

Similar Reads