JUnit, a Testing Library

The tool we will use to write and run tests is JUnit. It is a third-party library, separate from the Java language and its standard library. JUnit is the most widely used library for testing Java code. Because it is separate, we have to bring it into our project ourselves before we can use it.

Bringing in the library

In a large project you would normally let a build tool like Maven or Gradle fetch libraries for you. This course deliberately does not use a build tool. Instead we “vendor” the library: we copy its .jar file directly into a lib/ directory in any project we create, and put it on the classpath when we compile and run. You are not expected to know how to do this on your own. It is already done for you in the codebase that comes with this chapter and with every chapter after it. The rest of this section explains how it works, so you can understand the commands in the scripts/test.sh file.

JUnit ships as a single self-contained jar that bundles everything we need: the part that runs tests and the part that provides the assertions. We place that jar in a lib/ directory at the top level of our project:

lib/
  junit-platform-console-standalone-6.1.0.jar

Where tests live

Our code and our tests are in the same project, but in separate trees. Source code goes under src/main/, and tests go under src/test/, with the test package mirroring the source package. The test for a class Foo is a class FooTest in the matching path:

src/
  main/
    list/
      ArrayList.java
  test/
    list/
      ArrayListTest.java

Mirroring the package means the test is in the same package as the class it checks (package list; in both), so it can reach package-private members without us exposing anything just for testing.

Compiling and running

There are two commands. The first compiles all of our source and test files into an out/ directory, with the JUnit jar on the classpath. The second passes out/ to JUnit:

javac -d out -cp "lib/*" $(find src/main src/test -name "*.java")

java -jar lib/junit-platform-console-standalone-6.1.0.jar execute -cp out --scan-classpath

The execute subcommand is required, and --scan-classpath tells JUnit to look through the compiled out/ directory and discover the tests on its own. The project keeps both commands in scripts/test.sh, and you just run that script. If you use an IDE like IntelliJ IDEA, it will automatically recognize the project structure and let you run tests with a click (a play button next to the test class or method).