Skip to content

Fix test isolation to prevent order-dependent failures#539

Merged
Reetus merged 2 commits into
ccchangesfrom
fix/test-isolation-cleanup
Mar 30, 2026
Merged

Fix test isolation to prevent order-dependent failures#539
Reetus merged 2 commits into
ccchangesfrom
fix/test-isolation-cleanup

Conversation

@Reetus
Copy link
Copy Markdown
Owner

@Reetus Reetus commented Mar 30, 2026

Add/enhance [TestCleanup] methods across 10 test classes to properly reset shared static state (Engine.Player, Items, Mobiles, aliases, Options) after each test. Replace Engine.Install() with Initialize() + InitializePlugin() in EngineTests to prevent SplashWindow from appearing.

Summary by CodeRabbit

  • Tests
    • Improved test isolation and cleanup across multiple suites with new centralized teardown hooks to reset shared engine and command state between tests.
    • Standardised initialization flow in affected tests to ensure predictable setup and teardown, reducing flaky tests and improving overall test reliability.

Add/enhance [TestCleanup] methods across 10 test classes to properly
reset shared static state (Engine.Player, Items, Mobiles, aliases,
Options) after each test. Replace Engine.Install() with Initialize() +
InitializePlugin() in EngineTests to prevent SplashWindow from appearing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 30, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 1bdeb124-40c3-4e43-8678-710e64e81fc6

📥 Commits

Reviewing files that changed from the base of the PR and between 58b7798 and 5f8fbf7.

📒 Files selected for processing (1)
  • ClassicAssist.Tests/MacroCommands/PropertiesCommandTests.cs
🚧 Files skipped from review as they are similar to previous changes (1)
  • ClassicAssist.Tests/MacroCommands/PropertiesCommandTests.cs

Walkthrough

Updated tests to initialize the engine differently in EngineTests and to add or extend [TestCleanup] methods across many test classes to reset shared Engine and test-state (Player, Items, Mobiles, packet entries, aliases, options) after each test for improved isolation.

Changes

Cohort / File(s) Summary
Engine initialization change
ClassicAssist.Tests/EngineTests.cs
Replaced Engine.Install((PluginHeader*)func) calls with Engine.Initialize() followed by Engine.InitializePlugin((PluginHeader*)func) in several tests, ensuring the engine is initialized before plugin registration.
Added TestCleanup across tests
ClassicAssist.Tests/IncomingPacketHandlerTests.cs, ClassicAssist.Tests/MacroCommands/AliasCommandTests.cs, ClassicAssist.Tests/MacroCommands/JournalCommandsTests.cs, ClassicAssist.Tests/MacroCommands/PropertiesCommandTests.cs, ClassicAssist.Tests/MacroCommands/TargetCommandTests.cs, ClassicAssist.Tests/SpellCommandsTests.cs
Introduced [TestCleanup] public void Cleanup() methods that reset shared state after each test: nulling Engine.Player, reinitializing Engine.Items/Engine.Mobiles, clearing AliasCommands._aliases, resetting Engine.PacketWaitEntries/Engine.Journal, and restoring option flags as applicable.
Expanded existing cleanup methods
ClassicAssist.Tests/MacroCommands/ActionCommandTests.cs, ClassicAssist.Tests/MacroCommands/ObjectCommandTests.cs, ClassicAssist.Tests/OutgoingPacketHandlerTests.cs
Extended existing Cleanup() implementations to also clear global/static state (e.g., Engine.Player, Engine.Items, Engine.Mobiles, alias and ignore lists, packet wait entries) in addition to prior cleanup steps.
PropertiesCommandTests handler field addition
ClassicAssist.Tests/MacroCommands/PropertiesCommandTests.cs
Added private field Engine.dSendRecvPacket _internalPacketSentHandler and moved event-subscription handling to use that stored delegate; centralized teardown unsubscribes and nulls the handler and clears related Engine packet entries.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.26% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the primary change: fixing test isolation by preventing order-dependent failures through cleanup mechanisms.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/test-isolation-cleanup

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
ClassicAssist.Tests/EngineTests.cs (1)

113-114: Extract repeated engine/plugin initialisation into one helper.

These four tests duplicate the same setup block. Centralising it will reduce drift and keep initialisation changes in one place.

♻️ Proposed refactor
+        private unsafe void InitializeEngineAndPlugin()
+        {
+            fixed ( void* func = &_pluginHeader )
+            {
+                Engine.Initialize();
+                Engine.InitializePlugin( (PluginHeader*) func );
+            }
+        }

         [TestMethod]
         public unsafe void WillSendPacket()
         {
-            fixed ( void* func = &_pluginHeader )
-            {
-                Engine.Initialize();
-                Engine.InitializePlugin( (PluginHeader*) func );
-            }
+            InitializeEngineAndPlugin();
         }

         [TestMethod]
         public unsafe void WillFilterSendPacket()
         {
-            fixed ( void* func = &_pluginHeader )
-            {
-                Engine.Initialize();
-                Engine.InitializePlugin( (PluginHeader*) func );
-            }
+            InitializeEngineAndPlugin();
         }

         [TestMethod]
         public unsafe void WillFilterReceivedPacket()
         {
-            fixed ( void* func = &_pluginHeader )
-            {
-                Engine.Initialize();
-                Engine.InitializePlugin( (PluginHeader*) func );
-            }
+            InitializeEngineAndPlugin();
         }

         [TestMethod]
         public unsafe void WillReceivePacket()
         {
-            fixed ( void* func = &_pluginHeader )
-            {
-                Engine.Initialize();
-                Engine.InitializePlugin( (PluginHeader*) func );
-            }
+            InitializeEngineAndPlugin();
         }

Also applies to: 153-154, 202-203, 252-253

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ClassicAssist.Tests/EngineTests.cs` around lines 113 - 114, Four tests
duplicate the same Engine initialization block (calls to Engine.Initialize and
Engine.InitializePlugin((PluginHeader*) func)); extract that repeated setup into
a single private helper method (e.g., InitializeEngineWithPlugin or
SetupEngineAndPlugin) that performs Engine.Initialize and
Engine.InitializePlugin with the provided func pointer, then replace the
duplicated lines in the tests with a call to the new helper; ensure the helper
is accessible to the test methods and preserves any existing test state or
return values required by those tests.
ClassicAssist.Tests/MacroCommands/AliasCommandTests.cs (1)

22-27: Make teardown null-safe to avoid cleanup masking test failures.

If _aliases is ever uninitialised in a future test path, cleanup throws and hides the original failure signal.

Suggested fix
 [TestCleanup]
 public void Cleanup()
 {
     Engine.Player = null;
-    AliasCommands._aliases.Clear();
+    AliasCommands._aliases?.Clear();
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ClassicAssist.Tests/MacroCommands/AliasCommandTests.cs` around lines 22 - 27,
The teardown can throw if AliasCommands._aliases is null, masking real test
failures; modify the Cleanup method to null-check before clearing (e.g., only
call AliasCommands._aliases.Clear() if AliasCommands._aliases != null) and keep
Engine.Player = null as-is so cleanup is safe even when _aliases was never
initialized.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ClassicAssist.Tests/MacroCommands/PropertiesCommandTests.cs`:
- Around line 121-127: Cleanup does not unsubscribe the InternalPacketSentEvent
handler, causing leaks if WillWaitForProperties fails; modify
WillWaitForProperties to assign the delegate to a field (e.g.
_internalPacketSentHandler = OnInternalPacketSentEvent) before subscribing with
Engine.InternalPacketSentEvent += _internalPacketSentHandler, and update
Cleanup() to check and unsubscribe (Engine.InternalPacketSentEvent -=
_internalPacketSentHandler) and null the field so tests are fully isolated.

---

Nitpick comments:
In `@ClassicAssist.Tests/EngineTests.cs`:
- Around line 113-114: Four tests duplicate the same Engine initialization block
(calls to Engine.Initialize and Engine.InitializePlugin((PluginHeader*) func));
extract that repeated setup into a single private helper method (e.g.,
InitializeEngineWithPlugin or SetupEngineAndPlugin) that performs
Engine.Initialize and Engine.InitializePlugin with the provided func pointer,
then replace the duplicated lines in the tests with a call to the new helper;
ensure the helper is accessible to the test methods and preserves any existing
test state or return values required by those tests.

In `@ClassicAssist.Tests/MacroCommands/AliasCommandTests.cs`:
- Around line 22-27: The teardown can throw if AliasCommands._aliases is null,
masking real test failures; modify the Cleanup method to null-check before
clearing (e.g., only call AliasCommands._aliases.Clear() if
AliasCommands._aliases != null) and keep Engine.Player = null as-is so cleanup
is safe even when _aliases was never initialized.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: e2c15699-48f7-4f37-af17-6b9baec5b2f7

📥 Commits

Reviewing files that changed from the base of the PR and between 3e09f07 and 58b7798.

📒 Files selected for processing (10)
  • ClassicAssist.Tests/EngineTests.cs
  • ClassicAssist.Tests/IncomingPacketHandlerTests.cs
  • ClassicAssist.Tests/MacroCommands/ActionCommandTests.cs
  • ClassicAssist.Tests/MacroCommands/AliasCommandTests.cs
  • ClassicAssist.Tests/MacroCommands/JournalCommandsTests.cs
  • ClassicAssist.Tests/MacroCommands/ObjectCommandTests.cs
  • ClassicAssist.Tests/MacroCommands/PropertiesCommandTests.cs
  • ClassicAssist.Tests/MacroCommands/TargetCommandTests.cs
  • ClassicAssist.Tests/OutgoingPacketHandlerTests.cs
  • ClassicAssist.Tests/SpellCommandsTests.cs

Comment thread ClassicAssist.Tests/MacroCommands/PropertiesCommandTests.cs
Store InternalPacketSentEvent handler in a field and unsubscribe in
TestCleanup so the handler doesn't leak if WillWaitForProperties fails.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Reetus Reetus changed the base branch from master to ccchanges March 30, 2026 23:44
@Reetus Reetus merged commit 92d1b9a into ccchanges Mar 30, 2026
2 checks passed
@Reetus Reetus deleted the fix/test-isolation-cleanup branch March 30, 2026 23:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant