NRF SDK 0.9

Maintenance

Test your mod

Verify decisions, packaging and in-game behaviour with evidence appropriate to each level.

Test decisions without opening the game

Prerequisite: the first mod and its Gradle configuration. Create the file below in the same project. The plugin supplies kotlin.test and prepares resources for Windows tests.

src/test/kotlin/SignalTests.kt
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import nimby.*

class SignalTests {
    @Test fun unknownBlockStaysClosed() {
        val mod = nimby.mod.createMod()
        val decision = mod.evaluate(
            mapOf("active" to true),
            Observation(block = Occupancy.Unknown, fresh = true, routeKnown = true)
        )
        val indication = assertNotNull(mod.indication(decision)?.of(nimby.mod.firstSignal))
        assertEquals(nimby.mod.Aspect.Closed, indication.aspect)
        assertEquals(nimby.mod.Reason.Unknown, indication.reason)
    }

    @Test fun knownClearBlockOpens() {
        val mod = nimby.mod.createMod()
        val decision = mod.evaluate(
            mapOf("active" to true),
            Observation(block = Occupancy.Clear, fresh = true, routeKnown = true)
        )
        val indication = assertNotNull(mod.indication(decision)?.of(nimby.mod.firstSignal))
        assertEquals(nimby.mod.Aspect.Open, indication.aspect)
        assertEquals(nimby.mod.Reason.Clear, indication.reason)
    }
}
Run the tests
.\gradlew.bat windowsTest

The first test checks fallback behaviour; the second checks the normal case. mod.indication(decision)?.of(firstSignal) retrieves the model’s enums: compare their typed values, never the Decision.aspect code to a local ordinal. The tests also check the reason. For multiple models or neighbour dependencies, use evaluateNetwork with prepared Signal values and check each indication against its model.

Test inputResult to define
Unknown occupancy, stale observation or unknown routeAn explicit fallback without assuming the track is clear.
Unavailable setting, default value, numeric boundsA decision consistent with the setting contract.
Missing neighbour, different model, chain or cycleBounded resolution and a testable fallback.
Signal closed for two different reasonsThe expected driving instruction for each reason.
Animation immediately before, at and after a phase boundaryThe expected image for an explicitly supplied simulated time.

Verify each level separately

CheckWhat it establishesWhat remains to be checked
windowsTestRule results for the test inputs.Data and behaviour in a real game.
assembleReleaseModProduction of mod files and catalogue.Package loading and behaviour.
verifyNativeModLoading, stopping and reloading outside the game.Interactions with the game and its interface.
In-game testOutcome on the save, SDK and game used.Other maps, network sizes and scenarios.

An UP-TO-DATE report means that Gradle reuses a result whose inputs are unchanged. To rerun a task for a specific acceptance test, use --rerun-tasks and retain the command with its report. This is not required for every text change.

Acceptance check with explicit execution
.\gradlew.bat windowsTest verifyNativeMod --rerun-tasks

Make an in-game test reproducible

  • Prepare a test copy or save and record the starting point. Retain game, SDK and mod versions.
  • Define an observable result: aspect, applied driving instruction, panel, created objects or ticket result. Also define the expected refusal case.
  • Try pause, resume, several speeds and loading a game. Check that old-session data cannot trigger an action.
  • For a construction tool, check preview, confirmation, partial results, created objects and permitted undo.
  • Finish by closing your windows and connections and removing temporary effects. Record what was restored.