This guide provides instructions for setting up your system to run JUnit tests with Gradle.
Table of contents:
- Running JUnit 5 tests with Gradle
- What is Gradle?
- How to set up your project to run JUnit 5 unit tests with Gradle?
- How to create a JUnit test and use Gradle to run it?
- How to run specific tests only: filtering tests
- Analyzing the HTML test report that Gradle generates
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?
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
.
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.
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:
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:
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.
📈 Increase the efficiency of your unit tests
How to write JUnit test cases?
JUnit testing tips and tricks
- Part 1: How to ignore test cases in JUnit 4 and 5?
- Part 2: Tagging and filtering test cases in JUnit 4 & JUnit 5
- Part 3: Changing test execution order in JUnit 4 & JUnit 5
Using Symflower to improve your testing workflow
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.