Skip to content

🧪 RevFramework Status Effects — Testing Philosophy

This document explains how the Status Effects system is tested, what the tests are designed to protect, and what they intentionally do not claim.

This is not marketing material.

It is an engineering-facing overview of the testing philosophy behind the Status Effects system.


🎯 The Goal of the Tests

The Status Effects tests exist to protect:

  • behavioural guarantees
  • regression safety
  • deterministic runtime behaviour
  • explicit lifecycle semantics
  • stacking and refresh rules
  • authority-gated mutation behaviour
  • modifier and resistance behaviour
  • supported public extension seams
  • event and context attribution semantics
  • runtime helper behaviour such as auras and UI support

The tests are designed to answer questions like:

  • “Does this status still apply, refresh, tick, expire, and remove correctly after refactors?”
  • “Did a stacking policy accidentally change?”
  • “Does authority denial leave active state untouched?”
  • “Do potency and duration modifiers still flow through supported seams?”
  • “Does context attribution survive apply, refresh, remove, and expire?”
  • “Do optional helpers fail safely when integrations are missing?”

The goal is predictability, not “perfect software.”


🔒 Hostile Consumer Tests

Many Status Effects tests are written as Hostile Consumer tests.

This means the tests interact with the system the way a real project or advanced user would:

  • through public APIs
  • through supported interfaces
  • through supported components
  • through supported construction paths
  • through public utility methods
  • without relying on private implementation details
  • without assuming unsupported mutation patterns

These tests intentionally avoid treating internal implementation as a user-facing contract.

If a Hostile test passes, the supported public behaviour is behaving correctly.

Examples include:

  • StatusId equality and conversion behaviour
  • StatusContext construction helpers
  • TimedStatusEffect duration, ticking, refresh, extend, and remove behaviour
  • built-in status effect metadata and sink behaviour
  • ScriptableObject definition construction
  • StatusUtility apply and modifier helpers
  • StatusFx delegate hooks
  • StatusUseEvents
  • movement speed scaling
  • status icon library lookup
  • provider aggregation and default math service behaviour
  • missing-sink safety for optional integrations

⚙️ InternalTruth Tests

The Status Effects system also contains InternalTruth tests.

These tests validate framework assumptions that are important for long-term stability, even when those assumptions are not the primary user-facing learning surface.

Examples include:

  • controller apply / refresh / replace / stack semantics
  • stored context behaviour
  • lifecycle event and context event semantics
  • authority-gated mutation rules
  • authority resolver caching and invalidation
  • custom and paused time modes
  • immunity checks
  • potency and duration recomputation
  • stack caps
  • per-source stack refresh behaviour
  • dispel by type and tier
  • cleanse by tag
  • registry boot and custom registration behaviour
  • aura zone provider attachment and removal behaviour

InternalTruth tests are intentionally separated from Hostile tests.

They exist to protect framework integrity during future refactors.


🧩 What the Status Effects Tests Validate

The current Status Effects test suite validates behaviour including:

Core Value Types

  • StatusId equality
  • ordinal, case-sensitive identity
  • null string normalization
  • string conversion behaviour
  • StatusContext.None
  • item-use context construction
  • ability-use context construction
  • empty-context detection

Timed Effect Lifecycle

The tests validate that timed effects:

  • clamp negative duration to zero
  • apply with the expected remaining duration
  • tick down over time
  • clamp remaining time at zero
  • report expiration correctly
  • refresh remaining duration
  • extend remaining duration
  • remove cleanly
  • calculate normalized remaining time
  • call FX hooks in the expected apply / refresh / remove flow

These tests protect the shared base lifecycle used by built-in and custom timed effects.


Built-in Status Effects

The tests validate built-in effects including:

  • Poison metadata and damage ticking
  • Burn metadata and damage ticking
  • Slow movement multiplier application, retuning, and removal
  • Haste cooldown multiplier application, retuning, and removal
  • Vulnerability damage-taken multiplier application, retuning, and removal
  • Thorns metadata and stored reflection percentage
  • Stun behaviour toggling configured components
  • safe behaviour when optional target sinks are missing

The built-in statuses are tested as usable defaults and reference implementations.

They are not treated as mandatory gameplay design.


Definitions and Construction

The tests validate that ScriptableObject definitions build the expected runtime effect types.

This protects the authoring path where designers or tools construct statuses from assets.

Validated definition paths include:

  • Poison
  • Burn
  • Slow
  • Haste
  • Stun
  • Thorns
  • Vulnerability

Registry tests also validate:

  • built-in registry boot
  • known-id construction
  • stub construction
  • custom id registration
  • unknown-id failure behaviour

Controller Lifecycle

Controller tests validate:

  • replace behaviour removes existing matching effects
  • refresh behaviour updates existing effects instead of adding new ones
  • stack behaviour allows multiple instances
  • removal by id
  • removal by index
  • clear-all behaviour
  • active status queries
  • stack count queries
  • first-effect lookup
  • all-effect buffer lookup
  • expired effects being removed during update
  • expiration events firing

These tests protect the core runtime host semantics.


Stacking Policies

The tests validate:

  • default stack behaviour
  • per-id stack caps
  • oldest-stack refresh when caps are reached
  • per-source stack matching
  • same-source refresh behaviour
  • different-source stacking behaviour

This matters because stacking is one of the easiest places for future refactors to accidentally change gameplay semantics.


Context Attribution

Status context tests validate that source attribution is stored and surfaced consistently.

Covered attribution paths include:

  • ability source id
  • item source definition
  • instigator
  • source slot
  • notes
  • first-context query
  • context retrieval by effect instance
  • context event payloads on apply
  • context event payloads on refresh
  • context event payloads on remove
  • context event payloads on expire

These tests protect integration scenarios where UI, analytics, combat logs, item systems, or ability systems care about where a status came from.


Authority

Authority tests validate:

  • denied apply behaviour
  • allowed apply behaviour
  • denied tick behaviour
  • denied remove behaviour
  • denied clear-all behaviour
  • denied dispel behaviour
  • denied cleanse behaviour
  • denied duration recomputation
  • local authority resolution
  • parent authority resolution
  • scene-level resolver caching
  • cache invalidation
  • disabled cached authority replacement

Authority tests do not prove multiplayer correctness.

They prove that Status Effects respects the authority seam when one is configured.


Modifiers, Resistance, and Immunity

The tests validate:

  • immunity blocking status application
  • potency providers scaling adjustable magnitudes
  • resistance providers scaling duration
  • negative potency clamping safely
  • negative duration scale clamping safely
  • recomputing potency on active effects
  • recomputing durations on active effects
  • provider aggregation
  • default math service fallback behaviour

These tests protect the supported extension seams for buffs, debuffs, resistances, auras, difficulty modifiers, and custom gameplay rules.


Dispel and Cleanse

The tests validate:

  • dispel by type
  • dispel by minimum tier
  • non-matching dispel preservation
  • cleanse by tag mask
  • non-matching tag preservation
  • authority denial preserving state

These tests protect cleanse/dispel semantics as runtime mutation operations rather than loose utility calls.


Utility and Global Hooks

The tests validate utility surfaces including:

  • StatusUtility.ComputeFinalPotency
  • StatusUtility.ComputeFinalDurationScale
  • StatusUtility.Apply
  • missing-controller warning behaviour
  • StatusFx.Spawn
  • StatusFx.Pulse
  • StatusFx.Despawn
  • StatusUseEvents.RaiseApplied

These surfaces are intentionally lightweight, but they are still part of the supported integration story.


UI Helpers

Status Effects includes optional UI helpers.

The tests validate:

  • icon library missing-id behaviour
  • icon library successful lookup behaviour
  • stored icon entry data

These tests do not claim to validate every possible UI layout.

They protect the supported lookup surface used by buff bars and icon views.


Auras

Aura tests validate that aura zones can:

  • add potency providers to controller hosts
  • add resistance providers when duration scaling is enabled
  • reject actors by layer
  • reject actors by tag
  • resolve controller hosts from parents
  • request provider removal on exit / disable
  • participate in runtime trigger flow through PlayMode smoke tests

Auras are tested as optional runtime helpers.

They do not define a full area-of-effect combat system.


PlayMode Smoke Tests

The Status Effects suite includes targeted PlayMode smoke tests.

These validate:

  • controller ticking over real Unity frames
  • expiration through the real update loop
  • aura trigger provider add/remove flow in runtime physics

These tests are intentionally small.

They prove that the EditMode guarantees are not completely disconnected from real Unity runtime behaviour.

They are not full physics, networking, or gameplay simulation tests.


🧠 Deterministic Test Infrastructure

The Status Effects tests use focused test doubles and controlled Unity objects including:

  • simple timed test effects
  • adjustable metadata test effects
  • fake potency providers
  • fake resistance providers
  • fake immunity providers
  • custom time sources
  • local authority binders
  • recording damageable components
  • recording cooldown sinks
  • recording damage-taken modifiers
  • test behaviours for stun toggling
  • direct GameObject-based public API setups
  • controlled PlayMode smoke objects

These fakes are intentionally small and explicit.

They support:

  • lifecycle assertions
  • event assertions
  • context attribution assertions
  • authority-denial assertions
  • stack policy assertions
  • modifier/recompute assertions
  • safe missing-integration checks
  • repeatable runtime scenarios

This allows tricky status semantics to be tested reliably without requiring a full game project around them.


❌ What These Tests Do NOT Claim

The tests do not claim:

  • the framework is bug-free
  • every custom status effect is correct
  • every third-party integration is validated
  • every possible stacking combination is covered
  • multiplayer correctness is guaranteed
  • project-specific authority policy is validated
  • project-specific balancing is validated
  • every possible UI presentation is covered
  • every physics/aura edge case is covered
  • performance/stress limits are fully proven

The tests validate framework behaviour and guarantees — not every possible project implementation.


🧩 The Philosophy

RevFramework Status Effects is designed around:

  • explicit lifecycle semantics
  • predictable status mutation
  • supported public extension seams
  • clear stacking rules
  • safe context attribution
  • optional authority gating
  • modular modifier providers
  • lightweight utility and presentation hooks
  • reference implementations that can be replaced or extended

The tests exist to lock those guarantees down over time as the framework evolves.

The goal is not to pretend status effects are simple.

The goal is to make status behaviour understandable, stable, and intentional.


TL;DR

The Status Effects tests are designed to protect guarantees, not pretend software can never fail.

Hostile tests validate supported public behaviour.

InternalTruth tests protect runtime semantics and framework assumptions.

PlayMode smoke tests prove key runtime paths work in Unity’s real frame loop.

Together, they help keep Status Effects predictable as RevFramework evolves.