🧪 RevFramework Inventory — Testing Philosophy¶
This document explains how the Inventory 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 Inventory system.
🎯 The Goal of the Tests¶
The Inventory tests exist to protect:
- behavioural guarantees
- regression safety
- deterministic container behaviour
- explicit operation result semantics
- authority-aware service behaviour
- slot and stack mutation rules
- equipment lifecycle behaviour
- snapshot and restore semantics
- event and delta reporting
- supported public extension seams
- Unity lifecycle smoke safety
The tests are designed to answer questions like:
- “Does this inventory operation still behave the same after refactors?”
- “Does this failure path leave state untouched?”
- “Does this partial operation report the correct result?”
- “Does authority block service mutations consistently?”
- “Does direct local inventory mutation intentionally bypass service authority?”
- “Does equipment still preserve slot and filter rules?”
- “Does snapshot restore rebuild the intended state?”
- “Does search, sort, resize, transfer, or split still follow the documented contract?”
The goal is predictability, not “perfect software.”
🔒 Hostile Consumer Tests¶
Many Inventory 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 components
- through supported interfaces
- through supported service methods
- through supported snapshot helpers
- through supported item/equipment definitions
- without depending on private implementation details
- without treating internals as user-facing extension seams
These tests intentionally avoid pretending internal implementation is part of the supported public API.
If a Hostile test passes, the supported public behaviour is behaving correctly.
Examples include:
- adding items through
SceneInventoryService - removing items through public service calls
- moving and transferring stacks
- sorting and searching containers
- using
CharacterInventoryconvenience methods - equipping and unequipping through
CharacterEquipment - capturing and applying snapshot JSON
- using item effects through supported resolver seams
- validating authority-denied service operations
⚙️ InternalTruth Tests¶
The Inventory 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 public learning surface.
Examples include:
- direct
InventoryContainermutation semantics - merge-first then empty-slot placement rules
- split rollback behaviour
- event deferral and coalescing
- metadata equality and stackability rules
- internal delta tracking behaviour
- service authority ordering
- direct
CharacterInventoryauthority bypass truth - item use non-transactional behaviour
- resize/truncation edge behaviour
- current runtime truth around null-owner resize authority failure
InternalTruth tests are intentionally separated from Hostile tests.
They exist to protect framework integrity during future refactors.
🧩 What the Inventory Tests Validate¶
The current Inventory test suite validates behaviour including:
Containers¶
- lazy container creation
- owner/container isolation
- canonical container identifiers
- default container sizing
- size policy overrides
- read-only container views
- capacity reporting
- slot peeking
- non-empty slot counting
- clearing container state
- owner cleanup
Adding Items¶
- adding to empty slots
- merge-first placement
- max stack limits
- spillover into empty slots
- no-space failure behaviour
- all-or-nothing exact add behaviour
- add-max partial placement behaviour
- slot filter rejection
- no side effects when nothing can be added
- exact-space preflight consistency
Removing Items¶
- remove-by-GUID behaviour
- removal across multiple stacks
- remove-from-slot behaviour
- exact quantity removal
- not-enough-quantity failure
- item-not-found failure
- empty-slot failure
- invalid argument failure
- remove-up-to helper behaviour
- consume-exact helper behaviour
Splitting, Merging, Swapping, and Moving¶
- explicit split target behaviour
- auto-placement split behaviour
- split merge preference
- split rollback when full placement fails
- split rejection for whole-stack splits
- merge into compatible stacks
- partial merge into limited space
- already-full merge rejection
- merge rejection when stack identity differs
- merge-then-swap fallback
- swap between occupied slots
- swap between occupied and empty slots
- swap rejection when filters block the move
- same-owner moves
- cross-container moves
- exact target slot moves
- fallback placement when target slot is blocked
- no-space move failure without source mutation
Transfers¶
- full owner-to-owner transfers
- partial transfer behaviour
- partial transfer reported as failure by design
- no-space transfer rejection
- transfer rollback when destination cannot accept anything
- source/destination state preservation on failed transfer
- item database lookup requirement
- invalid argument handling
- authority denial handling
Authority¶
Inventory service mutations validate authority through the configured authority source.
The tests validate authority behaviour for:
- give exact
- add max
- remove by GUID
- remove from slot
- set slot
- swap
- merge-then-swap
- split
- move
- transfer
- resize
- sort
The tests also explicitly protect an important framework truth:
👉 Service mutations are authority-aware.
👉 Direct CharacterInventory container convenience methods bypass service authority.
That distinction is intentional and documented.
If authority matters, projects should route mutations through the authority-aware service layer.
Equipment¶
Equipment tests validate:
- equipment slot lookup
- slot key normalization
- case-insensitive slot lookup
- strict one-item equip behaviour
- swapped-item reporting
- quantity-one enforcement
- filter rejection
- unequip behaviour
- empty-slot unequip failure
- slot filter replacement
- clear-all behaviour
- deferred equipment events
CharacterEquipmentlazy initialization- equip from inventory
- unequip back to inventory
- equip event emission
- unequip event emission
- layout replacement
Equipment tests protect the distinction between:
- item storage
- equipment slot storage
- equipment acceptance filters
- gameplay meaning applied by the consuming project
Inventory verifies whether something can be equipped.
Your game decides what that equipped item actually does.
Item Definitions, Stacks, and Metadata¶
The tests validate item data behaviour including:
- GUID generation and normalization
- max stack clamping
- category normalization
- tag normalization
- database lookup
- duplicate GUID last-wins behaviour
- null/empty GUID handling
- metadata cloning
- metadata lookup
- duplicate metadata last-write-wins behaviour
- metadata replacement
- metadata removal
- stack equality
- durability comparison
- metadata-aware stackability
- ignored metadata keys for stackability
These tests protect item data as deterministic runtime state, not as game balance.
Search and Sort¶
Inventory search and sort tests validate:
- empty query returning all indices
- search by display name
- search by category
- search by tags
- no-match behaviour
- sort by name
- sort by rarity
- sort by category
- sort by quantity
- empty-slots-last behaviour
- already-sorted no-op behaviour
- no spurious delta emission when already sorted
The goal is stable user-facing container behaviour, not a full database query language.
Resize Behaviour¶
Resize tests validate:
- grow behaviour
- same-size no-op behaviour
- invalid size rejection
- shrinking empty tail slots
- blocking shrink when occupied tail slots would be lost
- truncating shrink when explicitly allowed
- returned truncated stacks
- authority-denied resize behaviour
- current runtime truth around resize/delta behaviour
Resize is tested because shrinking containers can destroy item state, so the rules must be explicit and stable.
Deltas and Events¶
Inventory delta tests validate:
- container changed events
- correct owner reporting
- correct container reporting
- changed slot indices
- before/after stack values
- swap reporting
- split reporting
- move reporting
- transfer reporting
- failed mutations not raising deltas
- denied mutations not raising deltas
- no spurious deltas for no-op sort
- event coalescing through deferred container events
This matters because game code often reacts to inventory events for:
- UI refreshes
- item pickup feedback
- equipment updates
- save dirty flags
- audio/VFX
- quest progress
- crafting availability
- shop refreshes
The tests protect the event signal from becoming noisy, missing, or misleading.
Snapshots and Restore¶
Snapshot tests validate:
- JSON capture
- JSON restore
- inventory roundtrip
- equipment roundtrip
- clearing existing state before restore
- invalid input handling
- missing database handling
- missing item skip policy
- missing item placeholder policy
- original GUID tagging on placeholders
- equipment quantity forced to one
- save/load JSON file helpers
Snapshots are tested as state restoration, not as gameplay item pickup, equip, or use operations.
The tests protect the difference between:
- “restore this saved state”
- and
- “perform gameplay mutations with gameplay consequences”
Item Use¶
Item use tests validate:
- null owner rejection
- missing service rejection
- out-of-range slot rejection
- empty slot rejection
- non-usable item rejection
- successful effect application
- item consumption after effect application
- default target resolution
- owner fallback target resolution
- unresolved effect behaviour
- external resolver behaviour
- boolean convenience wrappers
- authority-denied consumption behaviour
- non-transactional item use truth
The tests explicitly protect this important runtime behaviour:
👉 Item effects may apply before item consumption fails.
Inventory does not automatically roll back arbitrary gameplay effects.
That is intentional because effects may be external, project-specific, or non-reversible.
Projects that need transactional item use should implement that policy at their own gameplay layer.
UI and Binding¶
Inventory UI/binding tests validate:
- binder service resolution
- binder container resolution
- bind on enable
- cleanup on disable
- owner rebinding
- matching container mutation handling
- ignoring unrelated owner/container mutations
- safe behaviour when references are missing
These tests protect supported binding behaviour.
They do not claim to validate every possible production UI implementation.
Unity Lifecycle and PlayMode Smoke Coverage¶
Most Inventory behaviour is deterministic and is therefore best tested in EditMode.
Inventory has limited dependency on frame timing, physics, animation, async loading, or input.
A small PlayMode smoke test exists to validate that the system can survive a real Unity frame lifecycle:
- service creation
- owner creation
- inventory binding
- item add
- equip
- snapshot capture
- state mutation
- snapshot restore
- post-frame verification
This is not intended to become a giant PlayMode suite.
It exists to catch Unity lifecycle explosions, not to duplicate deterministic EditMode coverage.
🧠 Deterministic Test Infrastructure¶
The Inventory tests use focused test doubles and controlled Unity objects including:
- test item builders
- test item databases
- fake inventory authorities
- controlled GameObjects
- controlled
SceneInventoryServiceinstances - controlled
CharacterInventoryinstances - controlled
CharacterEquipmentlayouts - test use effects
- explicit ScriptableObject item definitions
- direct service setup
- explicit item database seeding
- reflection only where needed to seed private Unity authoring fields for deterministic tests
These fakes are intentionally small and explicit.
They support:
- authority assertions
- event assertions
- mutation assertions
- rollback assertions
- snapshot roundtrip assertions
- resolver seam validation
- lifecycle smoke validation
- repeatable inventory state scenarios
The goal is not to mock the entire game.
The goal is to isolate Inventory behaviour so regressions are obvious.
❌ What These Tests Do NOT Claim¶
The tests do not claim:
- the framework is bug-free
- every possible item combination is covered
- every custom UI implementation is validated
- every custom item effect is reversible
- every third-party integration is tested
- multiplayer correctness is guaranteed
- network replication is provided
- project-specific authority rules are validated
- item economy balance is proven
- every possible save/load policy is covered
- every possible inventory UX is tested
- performance and stress limits are fully proven
The tests validate framework behaviour and guarantees — not every possible project implementation.
🧩 The Philosophy¶
RevFramework Inventory is designed around:
- explicit operation results
- predictable slot behaviour
- deterministic stack rules
- clear add/remove/move/transfer semantics
- authority-aware service mutations
- clear direct-wrapper boundaries
- stable equipment rules
- explicit snapshot semantics
- transparent failure codes
- supported extension seams
- public API usage
- internal truth protection for future refactors
The tests exist to lock those guarantees down over time as the framework evolves.
The goal is not to hide complexity.
The goal is to make Inventory behaviour understandable, stable, and intentional.
TL;DR¶
The Inventory 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 coverage catches Unity lifecycle explosions.
Together, they help keep Inventory predictable as RevFramework evolves.