Testing And Benchmarking in Java

Here’s the translation of the Go testing and benchmarking example to Java:

Unit testing is an important part of writing principled Java programs. The JUnit framework provides the tools we need to write unit tests, and we can use build tools like Maven or Gradle to run tests.

For the sake of demonstration, this code is in a single file, but it could be split into separate files. Testing code typically lives in a separate directory from the code it tests, often under a src/test/java directory.

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import static org.junit.jupiter.api.Assertions.*;

public class IntUtilsTest {

    // We'll be testing this simple implementation of an integer minimum.
    public static int intMin(int a, int b) {
        return Math.min(a, b);
    }

    // A test is created by writing a method with @Test annotation
    @Test
    public void testIntMinBasic() {
        int ans = intMin(2, -2);
        // assertEquals will report test failures
        assertEquals(-2, ans, "IntMin(2, -2) should be -2");
    }

    // Writing tests can be repetitive, so it's idiomatic to use
    // parameterized tests, where test inputs and expected outputs
    // are provided as parameters.
    @ParameterizedTest
    @CsvSource({
        "0, 1, 0",
        "1, 0, 0",
        "2, -2, -2",
        "0, -1, -1",
        "-1, 0, -1"
    })
    public void testIntMinParameterized(int a, int b, int expected) {
        int ans = intMin(a, b);
        assertEquals(expected, ans, 
            String.format("IntMin(%d, %d) should be %d", a, b, expected));
    }
}

For benchmarking in Java, we typically use a separate framework like JMH (Java Microbenchmark Harness). Here’s a simple example of how you might set up a benchmark:

import org.openjdk.jmh.annotations.*;
import java.util.concurrent.TimeUnit;

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Thread)
public class IntUtilsBenchmark {

    @Benchmark
    public void benchmarkIntMin() {
        IntUtilsTest.intMin(1, 2);
    }

    // To run the benchmark, you would typically set up a separate main method
    // or use a build tool plugin. The exact setup depends on your project structure.
}

To run the tests, you would typically use a build tool like Maven or Gradle. With Maven, you might run:

$ mvn test

This would output something like:

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running IntUtilsTest
Tests run: 6, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.068 sec

Results :

Tests run: 6, Failures: 0, Errors: 0, Skipped: 0

For benchmarks, the setup is more complex and typically involves adding JMH as a dependency and setting up a separate benchmark execution. The output would look something like:

Benchmark                   Mode  Cnt   Score   Error  Units
IntUtilsBenchmark.intMin    avgt    5   2.658 ± 0.053  ns/op

This indicates that the intMin method takes about 2.658 nanoseconds on average to execute.