Testing And Benchmarking in Logo

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 org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class IntegerUtilsTest {

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

    // A test is created by writing a method with @Test annotation
    @Test
    public void testIntMinBasic() {
        int ans = intMin(2, -2);
        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) {
        assertEquals(expected, intMin(a, b),
            String.format("IntMin(%d, %d) should be %d", a, b, expected));
    }

    // Benchmark tests in Java typically use a framework like JMH.
    // Here's a simple benchmark using JMH.
    @Benchmark
    @BenchmarkMode(Mode.AverageTime)
    public void benchmarkIntMin() {
        intMin(1, 2);
    }

    // To run the benchmark
    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(IntegerUtilsTest.class.getSimpleName())
                .forks(1)
                .build();

        new Runner(opt).run();
    }
}

To run all tests in the current project using Maven:

$ mvn test
-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running IntegerUtilsTest
Tests run: 6, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.086 sec

Results :

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

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

To run the benchmark (assuming you have set up JMH correctly in your project):

$ mvn clean install
$ java -jar target/benchmarks.jar
# JMH version: 1.29
# VM version: JDK 11.0.10, OpenJDK 64-Bit Server VM, 11.0.10+9
# VM invoker: /usr/lib/jvm/java-11-openjdk-amd64/bin/java
# VM options: <none>
# Warmup: 5 iterations, 10 s each
# Measurement: 5 iterations, 10 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Average time, time/op
# Benchmark: IntegerUtilsTest.benchmarkIntMin

# Run complete. Total time: 00:01:40

Benchmark                       Mode  Cnt   Score   Error  Units
IntegerUtilsTest.benchmarkIntMin  avgt    5   2.302 ± 0.011  ns/op

In this Java version:

  1. We use JUnit 5 for unit testing, which is the standard testing framework for Java.
  2. Instead of table-driven tests, we use parameterized tests, which is the JUnit way of running the same test with different inputs.
  3. For benchmarking, we use JMH (Java Microbenchmark Harness), which is the standard for microbenchmarking in Java.
  4. The structure of the tests is similar, but adapted to Java and JUnit conventions.
  5. Running tests and benchmarks typically involves using a build tool like Maven or Gradle, rather than direct command-line tools.

Remember to add the necessary dependencies (JUnit and JMH) to your project’s build file (pom.xml for Maven or build.gradle for Gradle) to run these tests and benchmarks.