Icon for gfsd IntelliJ IDEA

How to run JUnit 5 tests with Gradle: a step-by-step guide

An illustration to Symflower's step-by-step guide to running JUnit 5 tests with Gradle.

This guide provides instructions for setting up your system to run JUnit tests with Gradle.

Table of contents:

Running JUnit 5 tests with Gradle

When working in a Java context, you’ll come across the most popular build tools: Maven and Gradle. While Maven is by far the most popular build system (with 76% of Java developers relying on it), Gradle has a comfortable second place with 38% of developers using it. Since it’s a bit less well-known, we put together a step-by-step guide to running JUnit tests with Gradle.

Why write tests when you can generate them?

Symflower lets you generate smart test templates and complete test suites for your applications. Find out how Symflower makes your editor better, watch the video below to see test generation in action, and get in touch with us to find out how we could best support your workflow.

What is Gradle?

Gradle is an open-source build automation system that helps you build, test, and deploy software applications on a number of platforms. It doesn’t just help compile code, but also makes it easier to perform testing and helps package your applications for deployment.

As a Java developer, you’ll consider using Gradle as opposed to Maven if you’re looking for a more flexible build system. Gradle’s underlying structure is more general and it uses a programming language in its build configuration instead of XML. On the flip side, Gradle can also be seen as overly complicated with too many ways to do the same thing. One more thing to consider: some accounts claim that Gradle can be about twice as fast as Maven.

How to set up your project to run JUnit 5 unit tests with Gradle?

Automatically migrate JUnit 4 to JUnit 5.

OK, that’s it for introductions. Let’s start walking you through the steps of running JUnit using Gradle.

Set up Gradle

Gradle runs on Java, so as step one, you’ll need to make sure you have Java version 8 or above. Use the java -version command to verify. This should return something like the following:

openjdk version "19.0.2" 2023-01-17
OpenJDK Runtime Environment (build 19.0.2+7-44)
OpenJDK 64-Bit Server VM (build 19.0.2+7-44, mixed mode, sharing)

If you don’t yet have a compatible version of Java, this is a good place to start installing a dedicated Java version.

Once you have that out of the way, before you can start using JUnit 5 with Gradle, you’ll also need to check if you have the right version of Gradle installed. JUnit 5 is natively supported by Gradle versions 4.6 and up. (Before version 4.6 you had to use the junit-platform-gradle-plugin which has been long depricated, so we are recommending a newer version of Gradle to be productive.) To verify if you’re running version 4.6 or a more up-to-date version, use the gradle -v command. If you’re missing Gradle, check out the documentation for more info on the installation process.

Start up your project with Gradle

As a first step, you’ll need to initialize your Gradle project. Thankfully, Gradle offers a built-in task to get you started by setting up a basic Java project automatically. After creating the folder for your new project and switching to this directory, all you’ll need to do is run Gradle’s init task.

Executing gradle init will then take you through the process of selecting a few fundamental things for your project:

Select type of project to generate:

1: basic
2: application
3: library
4: Gradle plugin
Enter selection (default: basic) [1..4] 2

Choose 2: application as this will create the basic project structure for a Java application.

Select implementation language:

  1: C++
  2: Groovy
  3: Java
  4: Kotlin
  5: Scala
  6: Swift

Pick 3: Java for a Java application since we’re about to run some JUnit tests using Gradle.

Split functionality across multiple subprojects?:

1: no - only one application project
2: yes - application and library projects

Go with 1: no - only one application project since for now, we won’t need anything more complex than that.

Select build script DSL:

1: Groovy
2: Kotlin

Go with 2: Groovy for a build script DSL. While there are advantages to using Kotlin, Groovy is the more common domain-specific language used to define build scripts.

Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no) [yes, no]

no is the default choice and it will do for now, so type “no” or just hit enter to continue.

Select test framework:

1: JUnit 4
2: TestNG
3: Spock
4: JUnit Jupiter

If you want to use JUnit 4, roll with the first option. Since this post is about running JUnit 5 tests with Gradle, use JUnit Jupiter (a JUnit 5 component) as that provides the combination of programming model and extension model for writing tests and extensions in the JUnit 5 framework. Select 4: JUnit Jupiter.

Automatically migrate JUnit 4 to JUnit 5.

Project name (default: temp): The next step in the gradle init task is to name your project. For our example, we’ll just use gradle-demo.

Source package (default: gradle.demo): Finally, select a source package. The default gradle.demo will be just fine.

Once you’re done with all these steps, your new Gradle project is set up with a standard project structure that’s likely similar to what you’d use if you were to set these folders up manually:

├── app // The default root project folder for your application
│   ├── build.gradle // That's the build script configuration file that defines your project and its tasks. See more on this later!
│   └── src // This is where you'll look for production and testing code
│       ├── main
│       │   ├── java
│       │   │   └── gradledemo
│       │   │       └── App.java // Gradle created a simple demo app for you.
│       │   └── resources
│       └── test
│           ├── java
│           │   └── gradledemo
│           │       └── AppTest.java // Gradle also created a demo test file for you.
│           └── resources
├── gradle
│   └── wrapper // This folder contains the Gradle Wrapper's JAR file and configuration
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew // This is a script for executing builds using the Gradle Wrapper
├── gradlew.bat // That's the wrapper batch script for executing the build with Windows
└── settings.gradle // General settings for Gradle for this application.

The first file you’ll notice in that list is build.gradle, the auto-generated build script that we’ll be taking a detailed look at right away.

You may already be familiar with src, which contains your production and testing code in a typical folder structure.

The next element there that you may be wondering about is the Gradle Wrapper. Gradle recommends that you use the wrapper to execute a Gradle build to ensure you’re using a declared Gradle version. This is useful, for instance, if multiple developers work on the same project, as it helps make sure they all use the right Gradle version for their project – without having to manually install that version. You’ll also find gradlew and gradlew.bat which are used to execute the Gradle Wrapper. To learn more, check out Gradle's user guide.

Next up, you also have the settings.gradle file which contains high-level project configuration such as the project’s name and a definition of which projects should be included in the build.

Let’s now take a closer look at that build.gradle file!

The build.gradle file

At this point, your build.gradle file will have been created in your root project directory with the following contents:

plugins {
    // Apply the application plugin to add support for building a CLI application in Java.
    id 'application'
}

repositories {
    // Use Maven Central for resolving dependencies.
    mavenCentral()
}

dependencies {
    // Use JUnit Jupiter for testing.
    testImplementation 'org.junit.jupiter:junit-jupiter:5.9.1'

    // This dependency is used by the application.
    implementation 'com.google.guava:guava:31.1-jre'
}

application {
    // Define the main class for the application.
    mainClass = 'gradle.demo.App'
}

tasks.named('test') {
    // Use JUnit Platform for unit tests.
    useJUnitPlatform()
}

Gradle is by default kept really slim and offers few automation options. In order to add more tasks or conventions, you’ll have to use “plugins”. In the above build.gradle, a single plugin has been added which is called “application” to allow you to build Java applications. Refer to Gradle’s user guide for a list of available plugins.

Next, build.gradle specifies which dependencies are required by the project, and where the main class of the application is located. Lastly, it defines that JUnit Jupiter, i.e. JUnit 5, should be used for unit testing.

How to create a JUnit test and use Gradle to run it?

You’re now ready to start coding and testing! Conveniently enough, the gradle init task automatically added a basic function to your App.java file, as well as a corresponding test case. Here’s the basic example code you’re starting out with:

public class App {
    public String getGreeting() {
        return "Hello World!";
    }

    public static void main(String[] args) {
        System.out.println(new App().getGreeting());
    }
}

Running gradle init also automatically supplied a test case for that example function in AppTest.java:

class AppTest {
    @Test void appHasAGreeting() {
        App classUnderTest = new App();
        assertNotNull(classUnderTest.getGreeting(), "app should have a greeting");
    }
}

Let’s just add an additional test for demonstration purposes:

@Test void appHasAGoodbye() {
    App classUnderTest = new App();
    assertNotNull(classUnderTest.getGreeting(), "app should have a greeting");
}

Using Symflower to generate your unit tests

When working on a more complex implementation than our example, writing unit tests can take quite a bit of time, which is why it’s smart to (re)use boilerplate code. Symflower automatically generates templates for your unit test to save you time & manual effort. Check out the documentation to learn about Symflower’s features, and visit our website to learn about all the ways Symflower can help with your projects.

Running tests

Now, it’s time to run our tests with Gradle and see what results we get! To run tests, you’ll just use the gradle test command. Once you’ve hit enter, here’s what you should see in your command line:

BUILD SUCCESSFUL in 1s
3 actionable tasks: 3 executed

In case the above output carries too little information for you, Gradle offers the possibility to configure the logging that should be done while the tests are run. Add the following code snippet to your build.gradle file:

test {
   testLogging {
       events "failed", "passed", "skipped", "standardError","standardOut", "started"
   }
}

It specifies that Gradle should log all failed, passed, and skipped tests. In addition, log outputs to the standard error and standard output are logged as well. And finally, also the start event of a test is logged.

In order to re-run the tests you have to, use gradle cleanTest test. We’re using this because by default, gradle test will not run again if you made no actual changes to the code.

gradle cleanTest test shows:

> Task :app:test

AppTest > appHasAGoodbye() STARTED

AppTest > appHasAGoodbye() PASSED

AppTest > appHasAGreeting() STARTED

AppTest > appHasAGreeting() PASSED

BUILD SUCCESSFUL in 2s
4 actionable tasks: 3 executed, 1 up-to-date

As you can see, we receive more information on which tests are currently executed. Checkout the TestLogging documentation for more information on how to customize the generated log outputs.

How to run specific tests only: filtering tests

Let’s assume you only want to run a specific unit test in your test suite, because you are working on functionality of that test. Gradle offers two options to filter the execution of tests:

  • Define a filter in build.gradle.
  • Use the --test option in the command line.

Let’s look at the latter option which is more likely to be useful in your daily programming tasks.

In order to only run the test appHasAGoodbye you can use the following command:

gradle test --tests gradle.demo.AppTest.appHasAGoodbye

It produces the following output:

> Task :app:test

AppTest > appHasAGoodbye() STARTED

AppTest > appHasAGoodbye() PASSED

BUILD SUCCESSFUL in 1s
3 actionable tasks: 1 executed, 2 up-to-date

As you can see, only one of the two existing tests got executed. To learn more about the options you can use to filter which unit tests should be run, check out test filtering in the Gradle documentation.

To optimize efficiency when running unit tests, it makes sense to use test impact analysis to only execute tests that are affected by changes. Symflower’s test impact analysis solution led to a 29% reduction in test execution times on average during our benchmarks. Learn more.

Analyzing the HTML test report that Gradle generates

Finally, Gradle generates a fancy HTML report to make test analysis easier for you. Find the report in app/build/reports/tests/test/index.html. Here’s what the report’s summary page looks like:

The test summary generated by Gradle

You can see that 2 tests were run, with both of them successfully passing (no failures, 100% successful test run). Feel free to click around to dig deeper into your test results! Clicking on gradle.demo, then AppTest will take you to the test run results of each individual method:

The detailed test report generated by Gradle

And you’re done! You just set up Gradle, started up your first project, created a JUnit test, and used Gradle to run it. You’ve also accessed the HTML report to analyze your test results.

Automatically migrate JUnit 4 to JUnit 5.

Sign up for our newsletter to make sure you stay updated on future content about software development and software testing, and follow us on X, LinkedIn, or Facebook.

Try Symflower in your IDE to generate unit test templates & test suites
| 2023-03-19