MCJunitLib as a Minecraft Testing Tool - Jacob1225/pufferfish-minecraft-mod GitHub Wiki

What is MCJunitLib and why is it important for this project?

MCJunitLib is a minecraft testing library that makes minecraft forge mods automatically testable. A common testing issue for forge developers is asserting that code functions properly within the minecraft world. Evidently, without any connection to the transformation loader class environment, JUnit tests cannot reference Minecraft source code, thus developers cannot be confident that a user can interact with in-game structures as expected. Fortunately, this testing framework allows for two types of software tests: unit and integration tests. In this project our team chose to prioritize the use of this framework to mainly test the arcade machine structure. For the space invaders mod, the primary minecraft interaction is regarding the arcade machine block (i.e. placing, destroying and using the arcade machine).

Setting up McJunitLib

To integrate the library in a forge mod project, a few additions need to be made to the build.gradle file.

Adding McJunitLib as a dependency:

  • Add the maven repository url for the library in the build.gradle file.
  • Add the test dependency for McJunitLib; specifying the version and minecraft version.
  • Version 1.4.4 (latest) of McJunitLib and 1.16.5 of Minecraft are used in this repository.

View from build.gradle file:

image

Adding the Server Tests as a Run Configuration:

  • Navigate to the minecraft run configurations in the build.gradle file.
  • Add a ServerTest run configuration under the client and server configurations.
  • Add the argument “crashOnFailedTests” to stop the server when tests fail.
  • Important that the server stops running in automated environments such as circleci.

View from build.gradle file:

image

Generate the new ServerTest Configuration:

  • To add the new run configuration as a gradle task: click on the gradle tasks tab.
  • For eclipse, click on genEclipseRuns.
  • For IntelliJ, click on genIntellijRuns.
  • Let the new run configurations build and refresh the gradle tasks.
  • The new configuration will appear as runServerTest under gradles tasks.

View from Eclipse:

image

That concludes the setup for McJunitLib! At this point, the project has the ability to launch a dedicated server to run tests. Nevertheless, the tests still need to be written.


Writing tests with McJunitLib

  • All tests should be placed in the src/java/test directory.
  • Unit and integration tests should be separated into their own class files.
  • All resources needed to perform tests should be under src/java/resources.

Unit Tests

Unit tests can be written to interact with the server instance that will be running and should be designed to test small portions of code. Tests that would interact directly with the world should be written as integration tests. It is useful to use unit testing to test registration of structures, such as blocks, tile entities, items, etc. A good starting point is to assert that a block can be registered in the server and that basic block operations function as expected. In this project, our unit tests focus mainly on the registration component of structures described above. Moreover, these unit tests are automated with circleci and currently serve as a basis for any future development. In order words, our tests assert that the arcade machine blocks and tileentities are first being registered and that a player can interact with them. Therefore, if any additional code results in these unit tests failing, we know that our current structures have been broken.

Unit Test Structure

  • Create a new package under src/java/test.
  • In our project, the unit test package in com.project.pufferfish.unit.tests.
  • In the created package, create a new class to write the tests.

View of Testing Directory Structure:

image

  • Different test classes have been used to test different portions of code.
  • Test Class methods must be annotated with @Test to mark it as a unit test.
  • Ensure that method names are descriptive; they will be referenced in the output logs.

View of Example Unit Test:

image

  • This example test imports the standard JUnit assertions class.
  • The test then validates that the arcade machine block is not null.
  • Lastly, it asserts that the arcade block is registered as expected in minecraft.

Integration Tests

As mentioned above, integration testing is used to test direct interaction with the minecraft world. Tests can be written to simulate a player using items, placing blocks, breaking blocks, etc. Integration tests make use of the MCJunitLib helper class, which provides methods for simulating such actions. These types of test work by testing structure blocks generated from the minecraft world. Please refer to the structure blocks section to learn more.

Integration Test Structure

  • Create a new package under src/java/test.
  • In our project, the integration test package in com.project.pufferfish.integration.tests.
  • In the created package, create a new class to write the tests.
  • The test class should be annotated with the name of the testable .nbt structure with @IntegrationTestClass
  • Test Class methods must be annotated with @IntegrationTest to mark it as an integration test.
  • All methods must take the integration helper as an input parameter.

View of generated resources directory:

image

  • Here we label the test class as arcade_machine_tests, which references the above directory.
  • We also label the tests as arcade-machine, which references the arcade-machine.nbt structure block to test.

View of Example Integration Test:

image

  • @IntegrationTest(“arcade-machine”) represents the name of the .nbt file to test..
  • The test places the arcade machine block in a certain position and it asserts if it is correctly registered in that position.

Running the Tests

  • Run all tests locally by running the runServerTest gradle tasks.
  • The results for both unit and integration tests will be displayed in the console.

View of Test Output:

image

View of Test Results:

image