Repository navigation
Weapon Knockback Test Plan
Test plan for the weapon knockback fix (#302, merged in PR #410). How the fix works is on the Weapon Knockback page.
What I'm checking:
- An enemy hit by a weapon gets pushed back and stops chasing for a moment.
- It gets pushed away from the player, not from the middle of the hitbox.
- It starts chasing again afterwards, and normal enemy movement hasn't changed.
There are unit tests for the logic, and manual tests in-game for what it actually looks like.
-
Unit tests: JUnit 5 + Mockito with
GameExtension. The tests use a real Box2DPhysicsServiceand a mockedGameTimeso the frame time can be controlled. - Manual tests: desktop build
-
Controls:
Jlight attack,Kheavy attack,WASDto move -
Debug terminal (
F1):weapon knife|sword|bowto equip,upgrade knifefor the flurry,debug onto see hitboxes
To run just these tests:
cd source
./gradlew :core:test --tests "*PhysicsMovementComponentTest" --tests "*TouchAttackComponentTest"
(On Windows PowerShell it's .\gradlew.bat.)
| Test | What it checks | Expected |
|---|---|---|
| staggerKeepsKnockbackVelocityInsteadOfSteeringBack | This is the actual bug: steering shouldn't cancel knockback. | After stagger(0.1f), an update leaves the knocked-back velocity (-4) alone instead of resetting it to the chase speed (2.5). |
| steeringResumesOnceStaggerExpires | Enemies don't stay stunned forever. | Once the time is up, isStaggered() is false and the enemy goes back to chase speed. |
| shorterStaggerDoesNotCutALongerOneShort | Two hits close together don't shorten the first stagger. | After stagger(0.5f) then stagger(0.01f), it's still staggered 5 frames later. |
| negativeStaggerIsRejected | Bad input. | stagger(-1f) throws IllegalArgumentException. |
- How far enemies fly and how long they pause is about game feel, so it's tuned by playing rather than tested.
- There's no unit test yet for a hit that both knocks back and immobilises (the Medusa case). It was checked manually in review. A test that staggers and freezes the same entity and checks it still moves would close this gap.
- Enemies that set their own velocity in an AI task (dash, stampede) and bosses with their own movement get pushed but not staggered. This is listed as a limitation on Weapon Knockback.
- The full weapon -> hitbox -> enemy flow in an actual dungeon is only tested manually. The unit tests test
TouchAttackComponentandPhysicsMovementComponentdirectly.
Claude (Anthropic, Claude Code) was used to help write the tests and draft this test plan. I reviewed it before publishing.
## OverviewTest plan for the weapon knockback fix ([#302](https://github.com/UQcsse3200/2026-studio-4/issues/302), merged in [PR #410](https://github.com/UQcsse3200/2026-studio-4/pull/410)). How the fix works is on the [Weapon Knockback](Weapon-Knockback) page.
What I'm checking:
- An enemy hit by a weapon gets pushed back and stops chasing for a moment.
- It gets pushed away from the player, not from the middle of the hitbox.
- It starts chasing again afterwards, and normal enemy movement hasn't changed.
There are unit tests for the logic, and manual tests in-game for what it actually looks like.
-
Unit tests: JUnit 5 + Mockito with
GameExtension. The tests use a real Box2DPhysicsServiceand a mockedGameTimeso the frame time can be controlled. - Manual tests: desktop build
-
Controls:
Jlight attack,Kheavy attack,WASDto move -
Debug terminal (
F1):weapon knife|sword|bowto equip,upgrade knifefor the flurry,debug onto see hitboxes
To run just these tests:
cd source
./gradlew :core:test --tests "*PhysicsMovementComponentTest" --tests "*TouchAttackComponentTest"(On Windows PowerShell it's .\gradlew.bat.)
| Test | What it checks | Expected |
|---|---|---|
staggerKeepsKnockbackVelocityInsteadOfSteeringBack |
This is the actual bug: steering shouldn't cancel knockback. | After stagger(0.1f), an update leaves the knocked-back velocity (-4) alone instead of resetting it to the chase speed (2.5). |
steeringResumesOnceStaggerExpires |
Enemies don't stay stunned forever. | Once the time is up, isStaggered() is false and the enemy goes back to chase speed. |
shorterStaggerDoesNotCutALongerOneShort |
Two hits close together don't shorten the first stagger. | After stagger(0.5f) then stagger(0.01f), it's still staggered 5 frames later. |
negativeStaggerIsRejected |
Bad input. |
stagger(-1f) throws IllegalArgumentException. |
The tests that were already in this class still pass, so normal movement isn't affected.
| Test | What it checks | Expected |
|---|---|---|
knockbackPushesEnemyAwayFromWielderAndStaggersIt |
Push comes from the player, and the hit staggers the enemy. | Player at x=0, enemy at x=1, hitbox centred past the enemy at x=2. The enemy moves in the positive direction (away from the player) and is staggered. |
enemyResumesChasingAfterKnockbackStagger |
The enemy chases again after being hit. | After KNOCKBACK_STAGGER seconds it's not staggered anymore and moves back towards its target. |
noKnockbackMeansNoStagger |
Hits with no knockback (like knife slashes) keep the enemy in range. | Knockback 0 doesn't stagger the enemy. |
All the existing tests in this class (repeat contact damage, cooldowns, concealment, disposal) still pass, so enemies hitting the player still works the same.
| Check | What it covers |
|---|---|
| Game Unit Tests | All the tests above plus the rest of the project. |
| Java Format | google-java-format (./gradlew formatCheck). |
| SonarCloud | Quality gate, no new issues. I split attack() into applyKnockback() to get its cognitive complexity under 15. |
| Javadoc Test Build | Javadoc on the new public methods (stagger, isStaggered, setKnockbackSource). |
Setup: run the game, go into a dungeon room with enemies, press F1, equip a weapon (weapon knife / weapon sword / weapon bow), optionally debug on, then F1 again to close.
| Test | Steps | Expected |
|---|---|---|
| Sword pushes back | Swing the sword (J) at an enemy walking towards you. |
It gets pushed away and pauses for a moment before coming back. |
| Sword direction | Let an enemy get to your side and hit it with the start or end of the swing. | It always goes away from the player, never towards. |
| Bow pushes back | Shoot an enemy that's coming at you. | It gets pushed back in the direction the arrow was going and pauses. |
| Medusa | Hit Medusa in the first dungeon with each weapon. | She's pushed back, pauses for her hit recovery, then chases again. (Found in review: before the fix her freeze cancelled the push.) |
| Freeze still works | Use a freeze bomb on an enemy without attacking it. | It stays completely still until the freeze ends. |
| Knife flurry |
upgrade knife, then K next to an enemy. |
The two slashes don't push it, the last stab does. |
| Enemy comes back | Hit an enemy once and wait. | After about a quarter of a second it walks back at normal speed. |
| Repeated hits | Keep hitting the same enemy as it comes back. | It gets pushed every time and never gets stuck or stops chasing. |
| Less damage taken | Stand still and keep attacking one enemy. | You take a lot less contact damage than before the fix. |
| Walls | Knock an enemy into a wall. | It stops at the wall, doesn't go through. |
| Player unchanged | Let an enemy touch you. | You still get pushed and damaged like before, and player movement feels the same. |
| Enemies unchanged when not hit | Walk around without attacking. | Enemies chase at normal speed like before. |
- How far enemies fly and how long they pause is about game feel, so it's tuned by playing rather than tested.
- There's no unit test yet for a hit that both knocks back and immobilises (the Medusa case). It was checked manually in review. A test that staggers and freezes the same entity and checks it still moves would close this gap.
- Enemies that set their own velocity in an AI task (dash, stampede) and bosses with their own movement get pushed but not staggered. This is listed as a limitation on [Weapon Knockback](Weapon-Knockback).
- The full weapon -> hitbox -> enemy flow in an actual dungeon is only tested manually. The unit tests test
TouchAttackComponentandPhysicsMovementComponentdirectly.
Claude (Anthropic, Claude Code) was used to help write the tests and draft this test plan. I reviewed it before publishing.
Entities and Components
Input Handling
- Service Locator
- Loading Resources
- Logging
- Unit Testing
- Debug Terminal
- Animations
- Audio
- AI
- Physics
- Terrain
- Concurrency & Threading
- Settings