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.
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)
}
}.\gradlew.bat windowsTestThe 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 input | Result to define |
|---|---|
| Unknown occupancy, stale observation or unknown route | An explicit fallback without assuming the track is clear. |
| Unavailable setting, default value, numeric bounds | A decision consistent with the setting contract. |
| Missing neighbour, different model, chain or cycle | Bounded resolution and a testable fallback. |
| Signal closed for two different reasons | The expected driving instruction for each reason. |
| Animation immediately before, at and after a phase boundary | The expected image for an explicitly supplied simulated time. |
Verify each level separately
| Check | What it establishes | What remains to be checked |
|---|---|---|
| windowsTest | Rule results for the test inputs. | Data and behaviour in a real game. |
| assembleReleaseMod | Production of mod files and catalogue. | Package loading and behaviour. |
| verifyNativeMod | Loading, stopping and reloading outside the game. | Interactions with the game and its interface. |
| In-game test | Outcome 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.
.\gradlew.bat windowsTest verifyNativeMod --rerun-tasksMake 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.