Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add game test section #279

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 41 additions & 5 deletions develop/automatic-testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ This page explains how to write code to automatically test parts of your mod. Th

Unit tests should be used to test components of your code, such as methods and helper classes, while game tests spin up an actual Minecraft client and server to run your tests, which makes it suitable for testing features and gameplay.

::: warning
Currently, this guide only covers unit testing.
:::

## Unit Testing {#unit-testing}

Since Minecraft modding relies on runtime byte-code modification tools such as Mixin, simply adding and using JUnit normally would not work. That's why Fabric provides Fabric Loader JUnit, a JUnit plugin that enables unit testing in Minecraft.
Expand Down Expand Up @@ -61,7 +57,7 @@ For an explanation of what this code actually does, see [Codecs](./codecs#regist

Great, the first test worked! But wait, the second test failed? In the logs, we get one of the following errors.

@[code lang=java transcludeWith=:::automatic-testing:5](@/reference/latest/src/test/java/com/example/docs/codec/BeanTypeTest.java)
@[code lang=log transcludeWith=:::automatic-testing:5](@/reference/latest/src/test/java/com/example/docs/codec/BeanTypeTest.java)

This is because we're trying to access the registry or a class that depends on the registry (or, in rare cases, depends on other Minecraft classes such as `SharedConstants`), but Minecraft has not been initialized. We just need to initialize it a little bit to have registries working. Simply add the following code to the beginning of your `beforeAll` method.

Expand All @@ -87,3 +83,43 @@ Add this to your `.github/workflows/build.yml` file, below the `./gradlew build`
**/build/reports/
**/build/test-results/
```

## Game Tests {#game-tests}

Minecraft provides the game test framework for testing server-side features. Fabric additionally provides client game tests for testing client-side features, similar to an end-to-end test.

### Setting up Game Tests with Fabric Loom {#setting-up-game-tests-with-fabric-loom}

Both server and client game tests can be set up manually or with Fabric Loom. This guide will use Loom.

To add game tests to your mod, add the following to your `build.gradle`:

@[code lang=groovy transcludeWith=:::automatic-testing:game-test:1](@/reference/latest/build.gradle)

To see all available options, see [the Loom documentation on tests](./loom/fabric-api#tests).

#### Setting up Game Test Directory {#setting-up-game-test-directory}

::: info
You only need this section if you enabled `createSourceSet`, which is recommended. You can, of course, do your own gradle magic, but you'll be on your own.
:::

If you enabled `createSourceSet` like the example above, your gametest will be in a separate source set with a separate `fabric.mod.json`. The module name defaults to `gametest`. Create a new `fabric.mod.json` in `src/gametest/resources/` as shown:

<<< @/reference/latest/src/gametest/resources/fabric.mod.json

Note that this `fabric.mod.json` expects a server game test at `src/gametest/java/com/example/docs/FabricDocsGameTest`, and a client game test at `src/gametest/java/com/example/docs/FabricDocsClientGameTest`.

### Writing Game Tests {#writing-game-tests}

You can now create server and client game tests in the `src/gametest/java` directory. Here is a basic example for each:

::: code-group

<<< @/reference/latest/src/gametest/java/com/example/docs/FabricDocsGameTest.java [Server]

<<< @/reference/latest/src/gametest/java/com/example/docs/FabricDocsClientGameTest.java [Client]

:::

See the respective Javadocs in Fabric API for more info.
2 changes: 1 addition & 1 deletion reference/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id 'fabric-loom' version '1.9-SNAPSHOT' apply false
id 'fabric-loom' version '1.10-SNAPSHOT' apply false
id "com.diffplug.spotless" version "6.23.3" apply false
id 'checkstyle'
}
Expand Down
12 changes: 11 additions & 1 deletion reference/latest/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
def minecraftVersion = "1.21.4"
def yarnVersion = "1.21.4+build.4"
def fabricApiVersion = "0.114.0+1.21.4"
def fabricApiVersion = "0.116.1+1.21.4"

dependencies {
minecraft "com.mojang:minecraft:${minecraftVersion}"
Expand All @@ -13,3 +13,13 @@ test {
useJUnitPlatform()
}
// :::automatic-testing:2

// :::automatic-testing:game-test:1
fabricApi {
configureTests {
createSourceSet = true
modId = "fabric-docs-reference-test-${project.name}"
eula = true
}
}
// :::automatic-testing:game-test:1
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.example.docs;

import net.fabricmc.fabric.api.client.gametest.v1.FabricClientGameTest;
import net.fabricmc.fabric.api.client.gametest.v1.context.ClientGameTestContext;
import net.fabricmc.fabric.api.client.gametest.v1.context.TestSingleplayerContext;

@SuppressWarnings("UnstableApiUsage")
public class FabricDocsClientGameTest implements FabricClientGameTest {
@Override
public void runTest(ClientGameTestContext context) {
try (TestSingleplayerContext singleplayer = context.worldBuilder().create()) {
singleplayer.getClientWorld().waitForChunksRender();
context.takeScreenshot("fabric-docs-reference-singleplayer-test");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.example.docs;

import net.minecraft.block.Blocks;
import net.minecraft.test.GameTest;
import net.minecraft.test.TestContext;

import net.fabricmc.fabric.api.gametest.v1.FabricGameTest;

public class FabricDocsGameTest implements FabricGameTest {
@GameTest(templateName = EMPTY_STRUCTURE)
public void test(TestContext context) {
context.expectBlock(Blocks.AIR, 0, 0, 0);
context.complete();
}
}
16 changes: 16 additions & 0 deletions reference/latest/src/gametest/resources/fabric.mod.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"schemaVersion": 1,
"id": "fabric-docs-reference-test",
"version": "1.0.0",
"name": "Fabric docs reference",
"icon": "assets/fabric-docs-reference/icon.png",
"environment": "*",
"entrypoints": {
"fabric-gametest": [
"com.example.docs.FabricDocsGameTest"
],
"fabric-client-gametest": [
"com.example.docs.FabricDocsClientGameTest"
]
}
}