본문으로 건너뛰기
버전: Minecraft 26.2

게임 테스트

게임 내 테스트는 Mojang의 게임 테스트 서버에서 실제 월드를 만들고 모드 코드를 실행해 결과를 확인합니다. 창이 뜨지 않고 EULA에 동의할 필요도 없어서, 코드를 고칠 때마다 돌리거나 CI에서 돌리기에 알맞습니다.

새 파일 GardenTests.java를 만듭니다.

src/main/java/com/example/crystalgarden/GardenTests.java
final class GardenTests {

private static final BlockPos ABOVE_FLOOR = BlockPos.of(0, 1, 0);

private GardenTests() {}

static void register(GameTestRegistrar tests) {
// A sprout reaches stage 1 after TICKS_PER_STAGE ticks on its own.
tests.register("sprout_grows", CrystalSprout.TICKS_PER_STAGE + 40, test -> {
test.setBlock(ABOVE_FLOOR, CrystalGardenMod.CRYSTAL_SPROUT);
BlockPos at = test.absolute(ABOVE_FLOOR);
test.runAfter(CrystalSprout.TICKS_PER_STAGE + 5, () -> {
int stage = test.world().stateAt(at).get(CrystalSprout.STAGE);
test.assertTrue(stage == 1, "stage after " + CrystalSprout.TICKS_PER_STAGE + " ticks is " + stage);
test.succeed();
});
});
// A ripe sprout gives crystals, starts again, and the harvest is counted for the player and the world.
tests.register("ripe_sprout_can_be_harvested", test -> {
test.setBlock(ABOVE_FLOOR, CrystalGardenMod.CRYSTAL_SPROUT);
BlockPos at = test.absolute(ABOVE_FLOOR);
test.assertTrue(CrystalSprout.ripen(test.world(), at), "the sprout ripened");
int harvestsBefore = test.world()
.storage(CrystalGardenMod.GARDEN_STATS, CrystalGardenMod.GARDEN_STATS_OPTIONS)
.data()
.getInt("harvests", 0);
PlayerView player = test.createMockServerPlayer();
test.useBlock(ABOVE_FLOOR, player);
test.assertTrue(
player.countItem(CrystalGardenMod.CRYSTAL) == CrystalSprout.CRYSTALS_PER_HARVEST,
"the player holds " + player.countItem(CrystalGardenMod.CRYSTAL) + " crystal(s)");
test.assertTrue(test.world().stateAt(at).get(CrystalSprout.STAGE) == 0, "the sprout starts again");
int counted = player.data(CrystalGardenMod.harvested).data().getInt("count", 0);
test.assertTrue(counted == CrystalSprout.CRYSTALS_PER_HARVEST, "the player's count is " + counted);
int harvests = test.world()
.storage(CrystalGardenMod.GARDEN_STATS, CrystalGardenMod.GARDEN_STATS_OPTIONS)
.data()
.getInt("harvests", 0);
test.assertTrue(harvests == harvestsBefore + 1, "the world counted " + harvests + " harvest(s)");
test.succeed();
});
// The server may use /garden grow; a fresh player may not.
tests.register("grow_command_needs_permission", test -> {
test.setBlock(ABOVE_FLOOR, CrystalGardenMod.CRYSTAL_SPROUT);
int result = test.runCommand("garden grow ~ ~1 ~");
test.assertTrue(result == 1, "/garden grow returned " + result);
int stage = test.world().stateAt(test.absolute(ABOVE_FLOOR)).get(CrystalSprout.STAGE);
test.assertTrue(stage == CrystalSprout.RIPE, "stage after /garden grow is " + stage);
PlayerView player = test.createMockServerPlayer();
test.assertTrue(
!player.hasPermission(CrystalGardenMod.growPermission), "a new player may not ripen sprouts");
test.succeed();
});
// The crystal block drops itself (the loot table polyResources generates) and is mined with a pickaxe.
tests.register("crystal_block_resources", test -> {
test.setBlock(ABOVE_FLOOR, CrystalGardenMod.CRYSTAL_BLOCK);
int matches = test.runCommand("execute if block ~ ~1 ~ #minecraft:mineable/pickaxe");
test.assertTrue(matches == 1, "the crystal block is in #minecraft:mineable/pickaxe");
int dropped = test.runCommand("loot spawn ~ ~2 ~ loot crystal_garden:blocks/crystal_block");
test.assertTrue(dropped == 1, "the loot table dropped " + dropped + " stack(s)");
test.succeed();
});
}
}

엔트리포인트의 마지막 줄에서 테스트를 등록합니다.

CrystalGardenMod.java (onInitializeCommon 끝)
GardenTests.register(mod.gameTests());
  • 테스트마다 작은 시험 구역이 주어집니다. 위치는 구역을 기준으로 한 상대 좌표이며(BlockPos.of(0, 1, 0)은 바닥 바로 위), test.absolute(...)로 월드 좌표를 얻을 수 있습니다.
  • 기본 제한 시간은 100틱입니다. sprout_grows는 새싹이 한 단계 자라는 105틱을 기다려야 하므로 TICKS_PER_STAGE + 40틱을 지정했습니다.
  • test.runCommand(...)는 서버 권한으로 실행되며 명령어의 결과값을 반환합니다.
  • createMockServerPlayer()는 접속하지 않은 가짜 플레이어입니다. 운영자가 아니므로 crystal_garden:grow 권한이 없습니다.

실행​

.\gradlew.bat gameTests "-PpolyTests=crystal_garden:*"

모두 통과하면 다음과 같이 끝납니다.

[GameTestServer] Each test that matches crystal_garden:* will be run 1 times (total: 4)
[GameTestServer] All 4 required tests passed :)

테스트가 실패하면 어느 테스트의 어떤 확인이 틀렸는지 the player holds 0 crystal(s) 같은 메시지로 알려 줍니다. 테스트 API 전체는 게임 내 테스트에서 확인할 수 있습니다.

다음 단계​

빌드·실행·배포에서 게임을 실행하고 jar를 배포합니다.

Buy me a coffee