Enemy Action and Form Animations Test Plan - UQcsse3200/2026-studio-3 GitHub Wiki

Enemy Action and Form Animations โ€” Test Plan (#438)

Owner: @jianghuichen0918 ยท Ticket: #438 (Sprint 4) ยท PRs: #463, #485 ยท Last updated: 2026-10-19

Feature page: Enemy Action and Form Animations

Test strategy

The work in #438 has three layers, and each is tested where it can actually be checked:

  • Atlas data (region names and frame counts). The .atlas files are plain text, so they are parsed directly without loading textures. This catches a misspelt or missing region, which would otherwise fail silently because the controller falls back to the normal animation.
  • Wiring code (EnemyFactory registering the animations and their timings, BattleController switching the Boss silence form). This is pure logic and is covered by JUnit with mocked atlases and real entities.
  • What the player sees (the poses, how long they stay, whether they line up with the old frames, and whether Team 7's effects still fit). Drawing needs a live LibGDX/OpenGL context, so these are checked manually in a running game using the F1 debug terminal.

The automated tests prioritise:

  • every region name agreed with #436, so Tianyu's form code finds the art by name;
  • the bestiary's default frame staying where it was;
  • fallback paths: an atlas without defend/cast must not crash;
  • the two timings changed on purpose (non-boss held poses, the enraged slash); and
  • the silence form starting and ending with the status, and not affecting other enemies or a defeated Boss.

Acceptance criteria coverage

# Acceptance criterion (#438) Covered by
1 Every enemy plays the matching animation when it defends or applies a debuff, then returns to idle EA01, EA02, EA06, EA07, EX01โ€“EX03; EM01โ€“EM04
2 All region names follow the naming convention and are read directly by Tianyu's code EA01โ€“EA04, EA08; EX03, EX04; EM03, EM04
3 Team 7's orbit visuals and attack lunge still work correctly with the new animations EM06
4 Enemy images in the bestiary are unchanged EA05; EM07

Silence-form cases (EA04, EA08, EA10, EM05) and the enraged slash timing (EA09) cover the extra work added in PR #485.

What was tested

Component Behaviour verified
Enemy atlases (lesser_shade, bone_crawler, dark_acolyte, tomb_guardian, void_knight, boss_knight) Every new region exists with the right frame count; default is still the first idle frame at xy: 0, 0
EnemyFactory defend and cast are registered for every enemy whose atlas has them and skipped when it does not; the Boss registers idle_silence; attack_enraged is held for 0.5 s while attack stays at 0.2 s
BattleController The Boss enters the silence form when the player is silenced and leaves it when the silence is removed; unrelated statuses, a defeated Boss and other enemies are ignored
EnemyAnimationController (#436, not changed by #438) Plays defend / cast when present, returns to idle, and uses the <animation>_<form> region while a form is active with a fallback to the normal one
In-game visuals Poses read clearly, line up with the old frames, stay for the intended time, and work with the status orbit, attack lunge and bestiary

Automated Test Cases

ID Component / test Why this case exists Case type Input or steps Expected result Actual result / evidence
EA01 EnemyAtlasRegionsTest.normalEnemiesHaveADefendPose Without a defend region these enemies fall back to idle and look like they stand still. Normal Parse lesser_shade, bone_crawler and dark_acolyte atlases and count regions by name. Each has exactly one defend frame. Pass โ€” local run 19 Oct 2026; CI on PR #463.
EA02 EnemyAtlasRegionsTest.tombGuardianHasDefendCastAndTauntingForm The Tomb Guardian needs an action pose for both its shield and its taunt, plus the taunting form. Normal Parse tomb_guardian.atlas. defend ร—1, cast ร—1, idle_taunt ร—2, hurt_taunt ร—1. Pass โ€” local run 19 Oct 2026; CI on PR #463.
EA03 EnemyAtlasRegionsTest.rivenKnightHasEnragedForm #436 looks the enraged form up by these exact names. Normal Parse void_knight.atlas. idle_enraged ร—2, attack_enraged ร—1, hurt_enraged ร—1. Pass โ€” local run 19 Oct 2026; CI on PR #463.
EA04 EnemyAtlasRegionsTest.bossHasSilenceForm The silence form only exists as two atlas entries; a repack of the Boss sheet could drop them unnoticed. Normal / regression Parse boss_knight.atlas. idle_silence ร—2. Pass โ€” local run 19 Oct 2026; CI on PR #485.
EA05 EnemyAtlasRegionsTest.defaultRegionIsStillTheFirstIdleFrame The bestiary (Team 5) shows default; adding frames must not move it. Regression For the five repacked atlases, find default and idle index 0. Both exist, default is at xy: 0, 0, and it matches idle frame 0. Pass โ€” local run 19 Oct 2026; CI on PR #463.
EA06 EnemyFactoryTest.nonBossEnemiesRegisterDefendAndCastWhenAtlasHasThem EnemyFactory used to register defend/cast for the Boss only. Normal Mock an atlas that returns a frame for every name; create bone_crawler and tomb_guardian. Both have defend and cast animations. Pass โ€” local run 19 Oct 2026; CI on PR #463 (test later revised by @xiaojaxon).
EA07 EnemyFactoryTest.enemiesWithoutDefendOrCastRegionsSkipThem Registering for every enemy must be safe when an atlas has no such region. Boundary / invalid Create lesser_shade with the default test atlas (no defend/cast), then call create(). Neither animation is registered and nothing throws. Pass โ€” local run 19 Oct 2026; CI on PR #463 (test later revised by @xiaojaxon).
EA08 EnemyFactoryTest.bossRegistersSilenceFormWhenAtlasHasIt The silence region in the atlas is useless unless the factory registers it as an animation. Normal Mock boss_knight.atlas with an idle_silence frame; create boss_knight. The animator has idle_silence. Pass โ€” local run 19 Oct 2026; CI on PR #485.
EA09 EnemyFactoryTest.enragedAttackIsHeldLongerThanNormalAttack The red slash is one frame; at 0.2 s it was gone before it could be seen. Only the enraged attack should change. Normal / regression Intercept the AnimationRenderComponent built for void_knight and verify its addAnimation calls. attack at 0.2 s and attack_enraged at 0.5 s, both NORMAL play mode. Pass โ€” local run 19 Oct 2026; CI on PR #485.
EA10 BattleControllerTest.shouldHoldBossSilenceFormUntilSilenceEnds Silence lives on the player, so the Boss must be told when it starts and ends; the switch must not leak to other enemies or a dead Boss. Normal / boundary / invalid Battle with a Boss and a Tomb Guardian. Apply Poison; apply then remove Silence; apply Silence again, set the Boss to 0 HP, remove Silence. Poison causes no form change; the Boss receives silence then normal; nothing is sent to the defeated Boss; the Tomb Guardian receives nothing. Pass โ€” local run 19 Oct 2026; CI on PR #485.

Existing tests this ticket relies on

These were written for #436 and were not changed by #438, but they are the other half of acceptance criteria 1 and 2, so they are run together with the cases above.

ID Component / test What it guarantees for #438 Actual result / evidence
EX01 EnemyAnimationControllerTest.shouldPlayDefendWhenAvailable enemyDefend plays the defend region added here. Pass โ€” local run 19 Oct 2026.
EX02 EnemyAnimationControllerTest.shouldPlayCastWhenAvailable, shouldReturnToIdleAfterCastFinishes enemyCast plays cast and then returns to idle. Pass โ€” local run 19 Oct 2026.
EX03 EnemyAnimationControllerTest.shouldHoldTauntIdleAndUseNormalCastWhenTauntCastIsMissing The taunting form uses idle_taunt and falls back to normal cast, which is why no cast_taunt art is needed. Pass โ€” local run 19 Oct 2026.
EX04 EnemyAnimationControllerTest.shouldUseEnragedHurtWhenAvailableAndReturnToNormalOnFormExit hurt_enraged is used in the enraged form, and leaving the form restores the normal animations. Pass โ€” local run 19 Oct 2026.

Manual Test Cases

All manual cases run in the desktop game (./gradlew desktop:run). Press F1 to open the debug terminal. Enemy slots start at 0. forceintent sets the enemy's next intent, so end the turn to see it act.

ID Area Why this case exists Steps Expected result Actual result / evidence
EM01 Normal-enemy defend poses Pose readability and alignment with the old frames cannot be asserted headlessly. On the map run goto <floor> combat (start with goto 1 combat). In battle run forceintent <slot> defend for each enemy, then end the turn. Repeat on other combat nodes until the Lesser Shade, Bone Crawler and Dark Acolyte have each been seen. Each plays its own pose (purple bubble, curled bone ball, golden ward) for about 0.8 s, then returns to idle. The feet stay on the same line and the body does not jump in size. The bubble and ward are see-through. Pending โ€” record a screenshot of each pose.
EM02 Tomb Guardian defend and taunt Two different action poses on one enemy must not be swapped. goto <floor> elite until a Tomb Guardian appears (debug on on the map shows floors). Run forceintent <slot> defend, end the turn; then forceintent <slot> taunt, end the turn. Defend shows the braced shield pose; taunt shows the laughing pose. Each lasts about 0.8 s. Pending โ€” record a screenshot of each pose.
EM03 Tomb Guardian taunting form The form must hold for as long as the taunt is on the player, then end. Continue from EM02 after the taunt lands. Attack the Tomb Guardian once, then play turns until the taunt icon leaves the player. While taunted, its idle is the laughing loop and a hit shows hurt_taunt. When the taunt ends it returns to its normal idle. Pending โ€” record a short clip.
EM04 Riven Knight enraged form and slash The red recolour and the 0.5 s slash are only meaningful on screen. goto <floor> elite until a Riven Knight appears. Run setenemyhp <slot> <hp below half its max>, end the turn, and let it attack. Hit it once. After its next intent it idles with red cracks instead of cyan. Its attack shows a red slash that stays visible for about half a second. A hit shows the red hurt frame. Pending โ€” record a short clip.
EM05 Boss silence form Checks the whole chain: intent โ†’ status on the player โ†’ BattleController โ†’ Boss form. On the map run debug on and read the floor of the final node, then goto <floor> final. Run forceintent <boss slot> silence, end the turn, and play turns until the silence icon leaves the player. The Boss casts, then keeps alternating two glowing cast frames for as long as the player is silenced. A hit plays the normal hurt frame and returns to the glow. It goes back to its normal idle when the silence ends. Pending โ€” record a short clip.
EM06 Team 7 status orbit and attack lunge Acceptance criterion 3: the orbit is sized from the current frame, and the new poses change that size. In a battle with a Lesser Shade, apply a status to it (e.g. Poison from a card), then forceintent <slot> defend and end the turn. Let any enemy attack. The orbit stays centred on the enemy and grows slightly around the bubble. The attack lunge moves forward and returns to the starting spot. Pending โ€” record a screenshot.
EM07 Bestiary images Acceptance criterion 4, checked through the real UI. Main Menu โ†’ Bestiary โ†’ Enemy Library. The library only lists enemies that have been discovered, so run it after EM01โ€“EM05 (or on a save that has met them). Open each of the six enemies. Each shows its normal form, same as before #438: no defend pose, red cracks, laughing pose or silence glow. Pending โ€” record a screenshot.

Run the automated tests from source/:

./gradlew core:test \
  --tests "*EnemyAtlasRegionsTest" \
  --tests "*EnemyFactoryTest" \
  --tests "*BattleControllerTest" \
  --tests "*EnemyAnimationControllerTest"

On Windows, use gradlew.bat in place of ./gradlew. The four classes contain 121 tests in total (5 + 26 + 60 + 30), including the 10 added for #438; all passed on 19 Oct 2026.

Sufficiency: Every new region name, both deliberate timing changes and the silence switch have a dedicated automated case, and each acceptance criterion maps to at least one case above. The atlas tests read the real asset files, so they also guard against a later repack. Whether a pose looks right, lines up with the old frames and fits Team 7's orbit can only be judged on screen, so those are manual cases. The silence form's behaviour when the Boss is defeated mid-silence is covered by EA10 only, because it is hard to time by hand. Manual rows stay pending until somebody records the real result and evidence; they must not be marked passed based on unit tests alone.

Status: Merged into Feature-1 through PR #463 (16 Oct 2026: defend and cast poses, taunting and enraged forms, tests EA01โ€“EA03, EA05โ€“EA07) and PR #485 (17 Oct 2026: Boss silence form, 0.5 s enraged slash, tests EA04, EA08โ€“EA10).

Test files:

source/core/src/test/com/csse3200/game/entities/factories/EnemyAtlasRegionsTest.java
source/core/src/test/com/csse3200/game/entities/factories/EnemyFactoryTest.java
source/core/src/test/com/csse3200/game/components/combat/BattleControllerTest.java
source/core/src/test/com/csse3200/game/components/enemy/EnemyAnimationControllerTest.java
โš ๏ธ **GitHub.com Fallback** โš ๏ธ