2. Testing

Running a main method is useful while learning syntax, but tests are better when you want repeatable checks. A test states what the code should do and lets Maven run that check every time the project changes.

2.1. Running tests

The example project uses JUnit. Run the test suite from source/code.

mvn test

Maven compiles the application code, compiles the test code, and then runs any test classes it discovers under src/test/java.

2.2. The existing test harness

The project includes a broad test that finds example classes and invokes their main methods. A few examples intentionally throw exceptions, so the harness ignores those classes.

1final Set<String> ignore = new HashSet<>() {{
2  add("com.oneoffcoder.java.TestAll");
3  add("com.oneoffcoder.java.exception.ThrowException");
4  add("com.oneoffcoder.java.exception.DivideByZero");
5}};

Each discovered class is wrapped in a Callable and executed by an executor.

 1  add("com.oneoffcoder.java.exception.DivideByZero");
 2}};
 3
 4List<Callable<Tuple>> callables = getClasses("com.oneoffcoder.java")
 5    .stream()
 6    .filter(c -> !ignore.contains(c.getName()))
 7    .map(c -> new TestWorker(c))
 8    .collect(Collectors.toList());
 9
10ExecutorService service = Executors.newFixedThreadPool(10);
11List<Future<Tuple>> futures = new ArrayList<>();
12for (var callable : callables) {

The final loop fails the JUnit test if any example failed unexpectedly.

1      }
2      return Optional.ofNullable(null);
3    })
4    .filter(o -> o.isPresent())
5    .map(o -> (Tuple)o.get())

2.3. A small unit test

Most production tests are narrower than the example harness. They call one method and compare the actual result to the expected result.

package com.oneoffcoder.java;

import org.junit.Assert;
import org.junit.Test;

public class ArithmeticTest {

  @Test
  public void addsTwoNumbers() {
    int result = 2 + 3;
    Assert.assertEquals(5, result);
  }
}

Good tests usually follow the same pattern: arrange the input, act by calling the code under test, and assert the result.

2.4. Testing exceptions

Some code should throw an exception for invalid input. JUnit can make that expectation explicit.

@Test(expected = ArithmeticException.class)
public void divisionByZeroFails() {
  int result = 10 / 0;
}

That test passes only when ArithmeticException is thrown.