MiniJavaTestBuilder API Overview

The MiniJavaTestBuilder class offers the ability to assert expected behavior of System.out, System.err, and the exit status produced when running the MiniJava compiler. It can be used in JUnit tests generally like this:

@Test
public void testUsingMiniJavaTestBuilderExample() {
    new MiniJavaTestBuilder()
            .assertSystemOutMatches("expected system out")
            .assertSystemErrIsEmpty()
            .assertExitSuccess()
            .testCompiler("-X", "filename.java", ...)
}

All of the assertions before testCompiler are optional and can be supplied in any order. Thus, the following is also a valid use of MiniJavaTestBuilder:

@Test
public void testUsingMiniJavaTestBuilderAnyAssertionOrder() {
    new MiniJavaTestBuilder()
            .assertExitFailure()
            .assertSystemErrMatches("expected system err")
            .testCompiler(...)
}

Assertions For System.out and System.err

In general, you can assert that the printed contents to System.out and/or System.err matches some expected String:

new MiniJavaTestBuilder()
        .assertSystemOutMatches("...")
        .assertSystemErrMatches("...")
        .testCompiler(...)

Since it's common to assert "it printed nothing," instead of using assertSystemXxxMatches(""), you can use:

new MiniJavaTestBuilder()
        .assertSystemOutIsEmpty()
        .assertSystemErrIsEmpty()
        .testCompiler(...)

For most test cases, the expected String is long and stored in files. Using this variant allows you to just pass in the path to those files:

  new MiniJavaTestBuilder()
          .assertSystemOutMatchesContentsOf(Path.of("folder", ..., "file"))
          .assertSystemErrMatchesContentsOf( pathToExpected )
          .testCompiler(...)

Tips

If none of these matches your needs, try pre-processing the expected String to match the actual String produced. For example, if your expected String has extra white spaces (for readability) where only a single whitespace is produced by the MiniJava compiler, you can remove those before passing it to the assertion method:
// condense multiple white spaces and/or newlines into a single whitespace
String preprocessed = expected.replaceAll("[\\s\\r\\n]+", " ");
new MiniJavaTestBuilder()
        .assertSystemOutMatches(preprocessed)
        .testCompiler("-S", inputFilepath);
If that still doesn't fit your need, see Advanced MiniJava Testing Utilities.

Assertions For Exit Status

You can use either assertExitSuccess or assertExitFailure to assert the exit status:

// asserts that the exit status is 0
new MiniJavaTestBuilder()
        .assertExitSuccess()
        .testCompiler(...)

// asserts that the exit status is 1
new MiniJavaTestBuilder()
        .assertExitFailure()
        .testCompiler(...)

Custom Assert Messages

If you would rather have your own message when an AssertionError is thrown, you can use the following overloaded methods:

Run and Test MiniJava.main

After adding all the assertions, you can ask MiniJavaTestBuilder to run MiniJava's main method through testCompiler, passing it all the args, if any:

// equivalent to asserting on results produced by java MiniJava -S filename.java
new MiniJavaTestBuilder()
        .assert...
        .testCompiler("-S", "filename.java")

// java MiniJava
new MiniJavaTestBuilder()
        .assert...
        .testCompiler()

// java MiniJava a b c d
new MiniJavaTestBuilder()
        .assert...
        .testCompiler("a", "b", "c", "d")

Testing Code Gen

Once you've implemented a fully working MiniJava compiler, a good way to test it is by comparing the output produced by the compiled binary against the output of the same program compiled by the actual Java compiler. You can do so using the MiniJavaTestBuilder like this:

new MiniJavaTestBuilder()
        .testCompiledProgramOutputMatchesJava(
                Path.of("SamplePrograms/SampleMiniJavaPrograms/"
                        "BinarySearch.java"));

Note

You cannot add any other assertions on a MiniJavaTestBuilder if you are performing this check.
To check that the assembly output matches expectations, make another MiniJavaTestBuilder object that uses testCompiler instead.

Testing Locally

Just like other parts of the project, you should always test your project on attu, a linux machine in the lab, or the CSE Virtual Machines . This is especially true for code generation, as assembly code generated for CSE Linux probably won't work on macOS/Windows/etc. Therefore, it's expected that running code gen tests will fail when you run them on your machine instead of on the CSE linux machines (attu, workstations, or CSE Linux Home VM).