IntelliJ IDEA 2023.2 Help

Test-driven development

Whether you like to write your tests before writing production code, or like to create the tests afterwards, IntelliJ IDEA makes it easy to create and run unit tests. In this tutorial we’re going to show how to use IntelliJ IDEA to write tests first (Test Driven Development or TDD).

Create a project

Create new project

  1. Launch IntelliJ IDEA.

    If the Welcome screen opens, click New Project. Otherwise, from the main menu, select File | New | Project.

  2. From the list on the left, select New Project.

  3. Name the new project, for example: MoodAnalyser and change its location if necessary.

  4. Select Java as the language for this project.

  5. Select Gradle as a build tool and Groovy as a DSL.

  6. From the JDK list, select the JDK that you want to use in your project.

    If the JDK is installed on your computer, but not defined in the IDE, select Add JDK and specify the path to the JDK home directory.

    If you don't have the necessary JDK on your computer, select Download JDK.

  7. Click Create.

IntelliJ IDEA creates a project with pre-configured structure and essential libraries. JUnit 5 will be added as a dependency to the build.gradle file.

Create a new package

  1. Right-click the main | java folder in the Project tool window and select New | Package.

  2. Name the new package com.example.demo and press Enter.

Write the test body

Create your first test

Given that we’re writing our tests first without necessarily having the code we’re testing available to us yet, we’ll create our first test via the project panel and place it in a package.

  1. Right-click the test root folder App modules test root and select New | Java Class.

    In the popup that opens, name the new package and test class: com.example.demo.MoodAnalyserTest.

    Test class created
  2. Place the caret inside the curly braces in the class, press Alt+Insert.

  3. Select Test Method from the menu to create a test method from the default template.

    Name the method testMoodAnalysis, press Enter, and the caret will end up in the method body.

    You can alter the default test method template - for example, if you wish to change the start of the method name from test to should.

Create a new class from the test

It may seem counter-intuitive to write test code for classes and methods that don’t exist, but IntelliJ IDEA makes this straightforward while keeping the compiler happy. IntelliJ IDEA can create classes and methods for you if they don’t already exist.

  1. Type new MoodAnalyser, press Alt+Enter, and select Create class 'MoodAnalyser'.

    Creating a new class from the test
  2. In the dialog that opens, select the com.example.demo package in the main | java folder and click OK.

    Selecting a destination package

Create variables

As always, you can use IntelliJ IDEA’s refactoring tools to create variables to store results in, and IntelliJ IDEA will import the most appropriate classes for you if the correct libraries are on the classpath.

  1. Switch back to the test class, type () and press Control+Alt+V to invoke the Extract/Introduce Variable refactoring.

  2. Name the new variable moodAnalyser.

Complete the test body

Continue writing the test body, including names of methods that you need that don’t exist.

  1. In the test class, type the following statement:

    moodAnalyser.analyseMood("This is a sad message");

    analyseMood will be marked as an unresolved reference.

  2. Place the caret at analyseMood, press Alt+Enter, and click Create method 'analyseMood' in 'MoodAnalyser'.

  3. Make sure the MoodAnalyser class looks as follows:

    public class MoodAnalyser { public String analyseMood(String message) { return null; } }
  4. In the test class, place the caret at analyseMood, press Control+Alt+V, and type mood.

    Introducing variable 'mood'

Add an assertion statement

  1. Open the build.gradle file, add the following dependency and click Load Gradle Changes to import the changes:

    dependencies { testImplementation( 'org.hamcrest:hamcrest-library:2.2' ) }
  2. In MoodAnalyserTest, add the following statement:

    assertThat(mood, CoreMatchers.is("SAD"));

    Import the missing methods and classes by pressing Alt+Enter.

Code

At this point, your test and production classes should look as follows:

package com.example.demo; public class MoodAnalyser { public String analyseMood(String message) { return null; } }
package com.example.demo; import org.hamcrest.CoreMatchers; import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; public class MoodAnalyserTest { @Test void testMoodAnalysis() { MoodAnalyser moodAnalyser = new MoodAnalyser(); String mood = moodAnalyser.analyseMood("This is a sad message"); assertThat(mood, CoreMatchers.is("SAD")); } }

Run the tests

When following a TDD approach, typically you go through a cycle of Red-Green-Refactor. You’ll run a test, see it fail (go red), implement the simplest code to make the test pass (go green), and then refactor the code so your test stays green and your code is sufficiently clean.

The first step in this cycle is to run the test and see it fail.

Given that we’ve used IntelliJ IDEA features to create the simplest empty implementation of the method we’re testing, we do not expect our test to pass.

  • From inside the test, press Control+Shift+F10 to run this individual test.

    The results will be shown in the run dialog. The test name will have an icon next to it — either red for an exception, or yellow for an assertion that fails. For either type of failure, a message stating what went wrong is also shown.

    Running the test

Implement the code

The next step is to make the tests pass, which means implementing the simplest thing that works. Often with TDD, the simplest thing that works might be hard-coding your expected value. We will see later how iterating over this process will lead to more realistic production code.

Fix the test

  1. In MoodAnalyser, replace null with the SAD return value: return "SAD";.

  2. Re-run the test, using Shift+F10 to re-run the last test.

    See the test pass - the icon next to the test method should go green.

    Rerunning tests

Iterate

Developing code is an iterative process. When following a TDD-style approach, this is even more true. In order to drive out more complex behaviour, we add tests for other cases.

Add the second test case

  1. In your test class, use Alt+Insert again to create a new test method. Name it HappyMoods.

  2. Add the following code to your class. Use refactoring tools to add the variable.

    @Test void HappyMoods() { MoodAnalyser moodAnalyser = new MoodAnalyser(); String mood = moodAnalyser.analyseMood("This is a happy message"); assertThat(mood, CoreMatchers.is("HAPPY")); }
  3. Run this second test case by pressing Alt+Shift+R, showing that it fails for the correct reason: in the Run tool window, click the Click to see difference link to open details in the Differences viewer.

Fix the second test

  1. Change the code in the method being tested to make this test pass:

    package com.example.demo; public class MoodAnalyser { public String analyseMood(String message) { if (message.contains(("sad"))) { return "SAD"; } else { return "HAPPY"; } } }
  2. Re-run both the tests by pressing Control+Shift+F10 inside the test class, not inside a single method, and see that both tests now pass.

    The second test passes

Summary

Writing your first test in a test-first style takes a small amount of setup – creating the test class, creating the test methods, and then creating empty implementations of the code that will eventually become production code. IntelliJ IDEA automates a lot of this initial setup.

As you iterate through the process, creating tests and then making the changes required to get those tests to pass, you build up a comprehensive suite of tests for your required functionality, and the simplest solution that will meet these requirements.

Last modified: 24 August 2023