Skip to content

Conversation

@dsarno
Copy link
Collaborator

@dsarno dsarno commented Oct 21, 2025

This PR consolidates the pytest test harness to focus exclusively on the MCPForUnity package, removing deprecated UnityMcpBridge paths and significantly improving test reliability and maintainability. All 51 tests now execute successfully (39 passed, 5 skipped, 7 xpassed).

The python server test infrastructure has been refactored to use proper imports and shared test helpers. Tests now correctly route through unity_connection for reliable monkeypatching, and telemetry has been updated to prefer explicit configuration with opt-in environment overrides rather than automatic file I/O. Common test utilities like DummyContext have been extracted to tests/test_helpers.py for reuse across the suite.

Several bugs were fixed, including a missing unity_connection prefix in validate_script and making the action parameter optional in read_console. The pyproject.toml now includes a [project.optional-dependencies] section with dev group containing pytest dependencies, and README-DEV.md has been updated with clear development setup instructions. This ensures contributors can quickly install dependencies with pip install -e .[dev] and run the full test suite.

Stats: 27 files changed, 606 insertions, 140 deletions

Summary by CodeRabbit

  • Bug Fixes

    • Fixed telemetry endpoint validation to properly respect environment overrides and fallback to configured defaults.
    • Made console action parameter optional with intelligent defaults.
  • Documentation

    • Added development setup guide with instructions for installing and running tests.
  • Tests

    • Improved test discovery and infrastructure for better isolation and reliability.
  • Chores

    • Updated project configuration and development dependencies for testing framework support.

dsarno added 11 commits October 10, 2025 06:53
…om tests; route tools.manage_script via unity_connection for reliable monkeypatching; fix ctx usage; all tests green (39 pass, 5 skip, 7 xpass)
…lidate_script; tests: tidy manage_script_uri unused symbols and arg names
…ests/test_helpers and import; add telemetry stubs in tests to avoid pyproject I/O
…config and opt-in env override; test stubs and CWD fixes; exclude Bridge from pytest discovery
…ore hook); telemetry: validate config endpoint; read_console: action optional
- Add [project.optional-dependencies] section with dev group
- Include pytest>=8.0.0 and pytest-anyio>=0.6.0
- Add Development Setup section to README-DEV.md with installation and testing instructions
@dsarno dsarno requested a review from Copilot October 21, 2025 17:29
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 21, 2025

Warning

Rate limit exceeded

@dsarno has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 18 minutes and 24 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between a607041 and dcd6907.

📒 Files selected for processing (9)
  • tests/test_edit_normalization_and_noop.py (7 hunks)
  • tests/test_edit_strict_and_warnings.py (4 hunks)
  • tests/test_get_sha.py (2 hunks)
  • tests/test_manage_script_uri.py (3 hunks)
  • tests/test_read_console_truncate.py (3 hunks)
  • tests/test_read_resource_minimal.py (2 hunks)
  • tests/test_script_tools.py (6 hunks)
  • tests/test_telemetry_queue_worker.py (4 hunks)
  • tests/test_validate_script_summary.py (2 hunks)

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

The PR refactors module imports across the codebase, changing direct function imports to module-level imports for better organization. It updates test infrastructure to use dynamic tool registration from a registry instead of decorator-based registration, introduces a DummyContext test helper for mocking, modifies endpoint selection logic in telemetry, and adds test collection safeguards to prevent duplicate test discovery across mirrored source directories.

Changes

Cohort / File(s) Summary
Configuration and Build
.gitignore, pytest.ini, MCPForUnity/UnityMcpServer~/src/pyproject.toml, docs/README-DEV.md
Added .wt-origin-main/ to gitignore, created pytest.ini with testpaths and norecursedirs exclusions, added dev extras with pytest dependencies, and documented development setup with testing instructions.
Core Module Refactoring
MCPForUnity/UnityMcpServer~/src/tools/manage_script.py, UnityMcpBridge/UnityMcpServer~/src/tools/manage_script.py
Changed from importing send_command_with_retry directly to importing the unity_connection module and routing all RPC calls through unity_connection.send_command_with_retry across multiple functions (read, apply_text_edits, create_script, delete_script, validate_script, get_sha, manage_script).
Other Tool Changes
MCPForUnity/UnityMcpServer~/src/tools/read_console.py
Made action parameter optional with default value of 'get' instead of required.
Telemetry Updates
MCPForUnity/UnityMcpServer~/src/telemetry.py
Modified module search order to prefer plain "config" and "src.config" entries, and changed endpoint selection logic to use environment override only if UNITY_MCP_TELEMETRY_ENDPOINT is set and non-empty, falling back to config default otherwise.
Test Infrastructure
tests/conftest.py, tests/test_helpers.py, UnityMcpBridge/UnityMcpServer~/src/conftest.py
Added collection ignore rules and pytest hook to skip duplicate test collection; introduced DummyContext mock class with no-op info/warning/error methods for test context mocking.
Test Files Refactoring
tests/test_edit_normalization_and_noop.py, tests/test_edit_strict_and_warnings.py, tests/test_find_in_file_minimal.py, tests/test_get_sha.py, tests/test_improved_anchor_matching.py, tests/test_manage_script_uri.py, tests/test_read_console_truncate.py, tests/test_read_resource_minimal.py, tests/test_resources_api.py, tests/test_script_tools.py, tests/test_telemetry_endpoint_validation.py, tests/test_telemetry_queue_worker.py, tests/test_telemetry_subaction.py, tests/test_validate_script_summary.py
Refactored test setup to dynamically import tool modules and retrieve registered tools from registry instead of direct decorator-based registration; updated monkeypatching to target unity_connection.send_command_with_retry instead of individual tool modules; replaced None context arguments with DummyContext() instances in tool invocations.
Unity Asset Metadata
TestProjects/UnityMCPTests/Assets/Temp.meta, TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/MaterialMeshInstantiationTests.cs.meta
Added Unity metadata files for asset folder and test script.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

The changes involve consistent refactoring patterns across multiple test files (homogeneous import and patching updates) combined with moderate complexity in telemetry logic changes and test infrastructure updates. While the spread is broad (20+ files), the repetitive nature of test refactors reduces per-file review burden. The production code changes (import strategy, endpoint logic) require focused analysis but are relatively localized.

Possibly related PRs

  • PR Improved ci prompt testing suite #270: Modifies UnityMcpBridge/UnityMcpServer~/src/tools/manage_script.py for response handling changes, directly overlapping with this PR's import refactoring in the same file.
  • PR Standardize how we define MCP tools #292: Extensive changes to the same manage_script.py file and tool registration patterns, directly overlapping with test infrastructure and module organization changes in this PR.
  • PR Make it easier to add tools #301: Introduces auto-discovery registry and mcp_for_unity_tool refactor that this PR's dynamic tool registration pattern depends on.

Suggested reviewers

  • justinpbarnett

Poem

🐰 A hop through imports, now modular and clean!
Registry tools dance where decorators once been,
DummyContext mocks our telemetry's stride,
Pytest discovers with nothing to hide.
Refactoring's magic—one module, one way! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ 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 "test: Consolidate pytest suite to MCPForUnity and improve test infrastructure" accurately captures the main objective of this PR. The changeset demonstrates comprehensive consolidation of the test harness toward MCPForUnity, including multiple test file refactorings to use dynamic tool registration, extraction of shared test helpers like DummyContext to tests/test_helpers.py, addition of pytest configuration files (pytest.ini and conftest.py with test collection safeguards), and infrastructure enhancements such as pyproject.toml dev dependencies and README-DEV.md documentation. While secondary changes like bug fixes to read_console and telemetry endpoint logic are also present, the title correctly prioritizes and reflects the primary focus of test consolidation and infrastructure improvement.

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

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR consolidates the pytest test suite to exclusively target the MCPForUnity package, removing legacy UnityMcpBridge references and significantly improving test infrastructure. The refactoring ensures all 51 tests execute successfully with proper import handling, shared test helpers, and reliable monkeypatching through unity_connection.

Key changes include:

  • Refactoring import mechanisms from deprecated package-style imports to direct module imports with proper sys.path management
  • Fixing bugs including missing unity_connection prefix in validate_script and making action parameter optional in read_console
  • Adding development dependencies to pyproject.toml and comprehensive setup instructions to README-DEV.md

Reviewed Changes

Copilot reviewed 27 out of 28 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/test_validate_script_summary.py Migrated to registry-based tool registration and proper unity_connection patching
tests/test_telemetry_subaction.py Replaced package-style import with manual module loading and telemetry stubs
tests/test_telemetry_queue_worker.py Added telemetry stub and working directory management for reliable module loading
tests/test_telemetry_endpoint_validation.py Refactored to use direct imports with sys.path injection and proper working directory
tests/test_script_tools.py Converted to registry-based registration and unity_connection patching
tests/test_resources_api.py Added telemetry stubs and migrated to registry-based tool setup
tests/test_read_resource_minimal.py Added DummyContext and registry-based tool registration
tests/test_read_console_truncate.py Updated to patch tools.read_console directly and added action parameter
tests/test_manage_script_uri.py Refactored to use registry-based registration and unity_connection patching
tests/test_improved_anchor_matching.py Updated module name from manage_script_edits to script_apply_edits
tests/test_helpers.py New shared test helper containing DummyContext class
tests/test_get_sha.py Migrated to registry-based registration and unity_connection patching
tests/test_find_in_file_minimal.py Added telemetry stubs and DummyContext import
tests/test_edit_strict_and_warnings.py Added telemetry stubs and refactored to registry-based registration
tests/test_edit_normalization_and_noop.py Updated module reference and migrated to registry-based registration
tests/conftest.py Added pytest collection ignores to prevent duplicate package imports
pytest.ini New configuration file defining test paths and exclusion rules
docs/README-DEV.md Added development setup instructions including dependency installation
UnityMcpBridge/UnityMcpServer~/src/tools/manage_script.py Changed import from direct function to module-based for unity_connection
UnityMcpBridge/UnityMcpServer~/src/conftest.py Added collection filter to avoid import conflicts
MCPForUnity/UnityMcpServer~/src/tools/read_console.py Made action parameter optional with default value
MCPForUnity/UnityMcpServer~/src/tools/manage_script.py Changed import from direct function to module-based for unity_connection
MCPForUnity/UnityMcpServer~/src/telemetry.py Updated config module resolution order and environment override logic
MCPForUnity/UnityMcpServer~/src/pyproject.toml Added optional dev dependencies section
.github/workflows/github-repo-stats.yml Commented out scheduled workflow trigger

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

collector.record(telemetry.RecordType.TOOL_EXECUTION, {"i": i})
elapsed_ms = (time.perf_counter() - start) * 1000.0

# Should be fast despite backpressure (non-blocking enqueue or drop)
Copy link

Copilot AI Oct 21, 2025

Choose a reason for hiding this comment

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

The timeout assertion was increased from 80ms to 200ms (a 150% increase). This suggests potential test flakiness or actual performance degradation. Consider investigating the root cause rather than simply relaxing the timeout threshold. If the backpressure test legitimately needs more time, document why this tolerance is appropriate.

Suggested change
# Should be fast despite backpressure (non-blocking enqueue or drop)
# Should be fast despite backpressure (non-blocking enqueue or drop)
# NOTE: The timeout threshold was increased from 80ms to 200ms due to observed test flakiness
# in CI and local environments, likely caused by thread scheduling variability and system load.
# If this test fails or performance degrades further, investigate the root cause (e.g., worker
# thread delays, queue contention, or changes in telemetry implementation) before increasing
# the threshold again. The 200ms value is chosen to balance reliability and detection of regressions.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Comment added to explain

Comment on lines +97 to 100
"config",
"src.config",
"MCPForUnity.UnityMcpServer~.src.config",
"MCPForUnity.UnityMcpServer.src.config",
Copy link

Copilot AI Oct 21, 2025

Choose a reason for hiding this comment

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

The module resolution order change is significant but lacks explanation. Add a comment explaining why plain 'config' is now preferred over package-qualified paths, especially regarding the test-time override behavior mentioned in the comment.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Comment added to explain

- Add explanation for 200ms timeout in backpressure test
- Replace manual event loop creation with asyncio.run()
- Add assertion message with actual elapsed time for easier debugging
Copy link
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: 7

♻️ Duplicate comments (1)
tests/test_edit_strict_and_warnings.py (1)

13-32: Telemetry stub duplication noted.

This is the same telemetry stub pattern duplicated across multiple test files. See the earlier comment on test_find_in_file_minimal.py recommending extraction to a shared fixture.

🧹 Nitpick comments (3)
UnityMcpBridge/UnityMcpServer~/src/conftest.py (1)

1-4: Suppress the unused parameter warning.

The config parameter is required by pytest's hook signature. Consider prefixing it with an underscore to indicate it's intentionally unused and silence the static analysis warning.

Apply this diff:

-def pytest_ignore_collect(path, config):
+def pytest_ignore_collect(path, _config):
     # Avoid duplicate import mismatches between Bridge and MCPForUnity copies
     p = str(path)
     return p.endswith("test_telemetry.py")
tests/test_telemetry_endpoint_validation.py (1)

10-18: Extract duplicated path setup into a fixture or module-level constant.

The path computation and sys.path manipulation is duplicated across all three test functions (lines 10-18, 33-39, 64-72). This should be extracted to avoid repetition and improve maintainability.

Consider extracting to module level:

+import sys
+import pathlib
+import importlib
+import os
+
+ROOT = pathlib.Path(__file__).resolve().parents[1]
+SRC = ROOT / "MCPForUnity" / "UnityMcpServer~" / "src"
+sys.path.insert(0, str(SRC))
+
 def test_endpoint_rejects_non_http(tmp_path, monkeypatch):
     # Point data dir to temp to avoid touching real files
     monkeypatch.setenv("XDG_DATA_HOME", str(tmp_path))
     monkeypatch.setenv("UNITY_MCP_TELEMETRY_ENDPOINT", "file:///etc/passwd")
 
-    # Import the telemetry module from the correct path
-    import sys
-    import pathlib
-    ROOT = pathlib.Path(__file__).resolve().parents[1]
-    SRC = ROOT / "MCPForUnity" / "UnityMcpServer~" / "src"
-    sys.path.insert(0, str(SRC))
-    
     monkeypatch.chdir(str(SRC))
     telemetry = importlib.import_module("telemetry")
     importlib.reload(telemetry)
tests/test_find_in_file_minimal.py (1)

14-33: Consider extracting telemetry stub setup into a shared fixture.

This telemetry stub pattern is duplicated across multiple test files (e.g., test_edit_strict_and_warnings.py, this file). Consider extracting it to conftest.py or a shared test utilities module.

Example approach in tests/conftest.py:

@pytest.fixture(autouse=True)
def stub_telemetry():
    """Stub telemetry modules to avoid file I/O during imports."""
    import sys
    import types
    
    telemetry = types.ModuleType("telemetry")
    def _noop(*args, **kwargs):
        pass
    class MilestoneType:
        pass
    telemetry.record_resource_usage = _noop
    telemetry.record_tool_usage = _noop
    telemetry.record_milestone = _noop
    telemetry.MilestoneType = MilestoneType
    telemetry.get_package_version = lambda: "0.0.0"
    sys.modules.setdefault("telemetry", telemetry)
    
    telemetry_decorator = types.ModuleType("telemetry_decorator")
    def telemetry_tool(*dargs, **dkwargs):
        def _wrap(fn):
            return fn
        return _wrap
    telemetry_decorator.telemetry_tool = telemetry_tool
    sys.modules.setdefault("telemetry_decorator", telemetry_decorator)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a81e130 and 8cdcda3.

📒 Files selected for processing (28)
  • .github/workflows/github-repo-stats.yml (1 hunks)
  • .gitignore (1 hunks)
  • MCPForUnity/UnityMcpServer~/src/pyproject.toml (1 hunks)
  • MCPForUnity/UnityMcpServer~/src/telemetry.py (2 hunks)
  • MCPForUnity/UnityMcpServer~/src/tools/manage_script.py (9 hunks)
  • MCPForUnity/UnityMcpServer~/src/tools/read_console.py (1 hunks)
  • TestProjects/UnityMCPTests/Assets/Temp.meta (1 hunks)
  • TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/MaterialMeshInstantiationTests.cs.meta (1 hunks)
  • UnityMcpBridge/UnityMcpServer~/src/conftest.py (1 hunks)
  • UnityMcpBridge/UnityMcpServer~/src/tools/manage_script.py (9 hunks)
  • docs/README-DEV.md (1 hunks)
  • pytest.ini (1 hunks)
  • tests/conftest.py (1 hunks)
  • tests/test_edit_normalization_and_noop.py (7 hunks)
  • tests/test_edit_strict_and_warnings.py (4 hunks)
  • tests/test_find_in_file_minimal.py (3 hunks)
  • tests/test_get_sha.py (2 hunks)
  • tests/test_helpers.py (1 hunks)
  • tests/test_improved_anchor_matching.py (4 hunks)
  • tests/test_manage_script_uri.py (3 hunks)
  • tests/test_read_console_truncate.py (3 hunks)
  • tests/test_read_resource_minimal.py (2 hunks)
  • tests/test_resources_api.py (4 hunks)
  • tests/test_script_tools.py (6 hunks)
  • tests/test_telemetry_endpoint_validation.py (3 hunks)
  • tests/test_telemetry_queue_worker.py (4 hunks)
  • tests/test_telemetry_subaction.py (1 hunks)
  • tests/test_validate_script_summary.py (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (17)
UnityMcpBridge/UnityMcpServer~/src/conftest.py (1)
tests/conftest.py (1)
  • pytest_ignore_collect (20-28)
tests/test_find_in_file_minimal.py (2)
tests/test_helpers.py (1)
  • DummyContext (1-10)
MCPForUnity/UnityMcpServer~/src/telemetry.py (1)
  • record_resource_usage (454-472)
tests/conftest.py (1)
UnityMcpBridge/UnityMcpServer~/src/conftest.py (1)
  • pytest_ignore_collect (1-4)
tests/test_improved_anchor_matching.py (1)
tests/test_script_tools.py (1)
  • load_module (32-36)
tests/test_validate_script_summary.py (3)
tests/test_manage_script_uri.py (5)
  • DummyContext (60-69)
  • info (62-63)
  • warning (65-66)
  • error (68-69)
  • DummyMCP (46-54)
tests/test_edit_normalization_and_noop.py (6)
  • DummyContext (50-59)
  • info (52-53)
  • warning (55-56)
  • error (58-59)
  • setup_tools (62-74)
  • DummyMCP (42-47)
UnityMcpBridge/UnityMcpServer~/src/tools/manage_script.py (2)
  • manage_script (443-500)
  • validate_script (409-439)
tests/test_script_tools.py (3)
tests/test_manage_script_uri.py (3)
  • info (62-63)
  • error (68-69)
  • DummyMCP (46-54)
UnityMcpBridge/UnityMcpServer~/src/tools/manage_script.py (1)
  • manage_script (443-500)
UnityMcpBridge/UnityMcpServer~/src/tools/manage_asset.py (1)
  • manage_asset (15-83)
tests/test_telemetry_queue_worker.py (2)
MCPForUnity/UnityMcpServer~/src/telemetry.py (1)
  • get_package_version (39-46)
UnityMcpBridge/UnityMcpServer~/src/telemetry.py (1)
  • get_package_version (37-44)
tests/test_get_sha.py (2)
tests/test_manage_script_uri.py (3)
  • info (62-63)
  • error (68-69)
  • DummyMCP (46-54)
UnityMcpBridge/UnityMcpServer~/src/tools/manage_script.py (2)
  • manage_script (443-500)
  • get_sha (536-552)
tests/test_telemetry_subaction.py (1)
MCPForUnity/UnityMcpServer~/src/telemetry.py (4)
  • MilestoneType (65-73)
  • record_resource_usage (454-472)
  • record_tool_usage (425-451)
  • get_package_version (39-46)
tests/test_read_console_truncate.py (2)
tests/test_manage_script_uri.py (4)
  • info (62-63)
  • warning (65-66)
  • error (68-69)
  • DummyMCP (46-54)
UnityMcpBridge/UnityMcpServer~/src/tools/read_console.py (1)
  • read_console (14-87)
tests/test_resources_api.py (4)
MCPForUnity/UnityMcpServer~/src/telemetry.py (1)
  • get_package_version (39-46)
MCPForUnity/UnityMcpServer~/src/telemetry_decorator.py (1)
  • telemetry_tool (17-107)
tests/test_helpers.py (1)
  • DummyContext (1-10)
MCPForUnity/UnityMcpServer~/src/tools/resource_tools.py (1)
  • list_resources (137-186)
tests/test_edit_normalization_and_noop.py (3)
tests/test_manage_script_uri.py (3)
  • info (62-63)
  • error (68-69)
  • DummyMCP (46-54)
tests/test_get_sha.py (4)
  • info (54-55)
  • error (60-61)
  • setup_tools (64-76)
  • DummyMCP (41-49)
UnityMcpBridge/UnityMcpServer~/src/tools/manage_script.py (1)
  • manage_script (443-500)
tests/test_read_resource_minimal.py (4)
tests/test_manage_script_uri.py (5)
  • DummyContext (60-69)
  • info (62-63)
  • warning (65-66)
  • error (68-69)
  • DummyMCP (46-54)
tests/test_edit_normalization_and_noop.py (5)
  • DummyContext (50-59)
  • info (52-53)
  • warning (55-56)
  • error (58-59)
  • DummyMCP (42-47)
tests/test_resources_api.py (2)
  • resource_tools (48-60)
  • DummyMCP (33-41)
tests/test_find_in_file_minimal.py (2)
  • resource_tools (48-60)
  • DummyMCP (36-44)
UnityMcpBridge/UnityMcpServer~/src/tools/manage_script.py (1)
UnityMcpBridge/UnityMcpServer~/src/unity_connection.py (1)
  • send_command_with_retry (416-436)
tests/test_manage_script_uri.py (2)
tests/test_edit_normalization_and_noop.py (5)
  • DummyContext (50-59)
  • info (52-53)
  • warning (55-56)
  • error (58-59)
  • DummyMCP (42-47)
UnityMcpBridge/UnityMcpServer~/src/tools/manage_script.py (1)
  • manage_script (443-500)
tests/test_telemetry_endpoint_validation.py (1)
MCPForUnity/UnityMcpServer~/src/telemetry.py (1)
  • TelemetryCollector (212-398)
tests/test_edit_strict_and_warnings.py (2)
tests/test_helpers.py (1)
  • DummyContext (1-10)
MCPForUnity/UnityMcpServer~/src/tools/manage_script.py (1)
  • manage_script (443-500)
🪛 Ruff (0.14.1)
UnityMcpBridge/UnityMcpServer~/src/conftest.py

1-1: Unused function argument: config

(ARG001)

tests/test_find_in_file_minimal.py

28-28: Unused function argument: dargs

(ARG001)


28-28: Unused function argument: dkwargs

(ARG001)

tests/test_edit_strict_and_warnings.py

27-27: Unused function argument: dargs

(ARG001)


27-27: Unused function argument: dkwargs

(ARG001)

🔇 Additional comments (28)
.github/workflows/github-repo-stats.yml (1)

4-7: Clarify why the scheduled workflow trigger was disabled.

This change disables the automatic daily stats collection and transitions the workflow to manual-only mode (workflow_dispatch). However, this change appears unrelated to the stated PR objectives (consolidating the pytest suite and improving test infrastructure).

Is this intentional? If so, please document the rationale in the PR description or as a separate change. If this was accidental, consider reverting it or moving it to a dedicated PR.

.gitignore (1)

42-43: LGTM!

The addition of .wt-origin-main/ fits naturally with the existing tool artifact patterns (e.g., .windsurf, .cursorignore) and cleanly ignores local development directory artifacts.

TestProjects/UnityMCPTests/Assets/Temp.meta (1)

1-8: Standard Unity asset metadata.

These are auto-generated Unity metadata files with proper YAML formatting and valid structure. No issues identified.

TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/MaterialMeshInstantiationTests.cs.meta (1)

1-11: Standard Unity asset metadata.

These are auto-generated Unity metadata files with proper YAML formatting and valid structure. No issues identified.

docs/README-DEV.md (1)

8-37: LGTM! Clear and accurate development setup documentation.

The instructions for installing dev dependencies and running tests are correct and align well with the pyproject.toml changes in this PR.

MCPForUnity/UnityMcpServer~/src/pyproject.toml (1)

14-18: LGTM! Standard dev dependencies configuration.

The optional dev dependencies are properly configured and align with the documentation changes in README-DEV.md.

MCPForUnity/UnityMcpServer~/src/telemetry.py (2)

96-98: Good addition for test-time flexibility.

Prioritizing plain "config" and "src.config" modules enables test-time sys.path injection and module overrides, which aligns well with the test infrastructure improvements in this PR.


120-126: No backward compatibility concern – behavior is identical.

The review comment's concern about empty string handling is not founded. Both the old and new code produce the same outcome when UNITY_MCP_TELEMETRY_ENDPOINT is set to an empty string:

  • Old code: os.environ.get("UNITY_MCP_TELEMETRY_ENDPOINT", default_ep) would pass "" to _validated_endpoint(), which would fail the netloc check and fall back to default_ep.
  • New code: Explicitly checks if env_ep != "" and also falls back to default_ep.

Result: identical behavior. Additionally, no code in the codebase explicitly sets this environment variable to an empty string, and the test suite contains no tests for this scenario, indicating it's not a deployed pattern.

MCPForUnity/UnityMcpServer~/src/tools/read_console.py (1)

16-16: LGTM! Backward-compatible parameter defaulting.

Making the action parameter optional with a sensible default ('get') improves the API ergonomics while maintaining full backward compatibility.

pytest.ini (1)

1-4: LGTM! Proper test collection configuration.

The exclusions prevent duplicate imports and collection conflicts between Bridge and MCPForUnity copies, which aligns well with the pytest hooks in the conftest.py files.

tests/test_improved_anchor_matching.py (1)

41-42: LGTM! Consistent module rename.

The module reference has been updated from manage_script_edits_module to script_apply_edits_module and all usages are consistently updated throughout the test file.

tests/test_helpers.py (1)

1-10: LGTM! Clean test helper extraction.

Centralizing the DummyContext mock in a shared test helper improves test maintainability and reduces code duplication across the test suite.

MCPForUnity/UnityMcpServer~/src/tools/manage_script.py (2)

9-9: LGTM: Import change enables better test isolation.

The change from direct function import to module import allows tests to patch unity_connection.send_command_with_retry at the module level, improving test reliability and maintainability.


106-110: LGTM: Consistent usage of module-level RPC calls.

All call sites correctly updated to use unity_connection.send_command_with_retry(...) instead of the direct import. The change preserves all parameters and behavior while enabling module-level patching in tests.

Also applies to: 307-307, 339-344, 389-390, 404-405, 429-429, 476-476, 544-545

tests/test_telemetry_queue_worker.py (2)

33-52: LGTM: Telemetry stub prevents file I/O during test setup.

The stub approach ensures get_package_version doesn't attempt to read pyproject.toml during module loading, improving test isolation and speed.


83-83: Timing assertion adjustment is reasonable.

The relaxation from 80ms to 200ms accounts for the additional overhead introduced by the stubbing and dynamic module loading infrastructure. The test still validates non-blocking behavior.

tests/test_find_in_file_minimal.py (2)

8-8: LGTM: Proper reuse of shared test helper.

Good use of the centralized DummyContext from test_helpers.py instead of defining it locally.


50-59: LGTM: Dynamic tool registration via registry.

The switch to registry-based tool discovery aligns with the PR's infrastructure improvements and enables better test isolation.

tests/test_validate_script_summary.py (2)

65-75: LGTM: Registry-based tool population.

The dynamic tool registration approach correctly aligns with the PR's infrastructure improvements and enables better test isolation.


95-98: LGTM: Module-level patching strategy.

Patching unity_connection.send_command_with_retry at the module level (rather than patching individual tool references) is the correct approach that aligns with the production code changes in manage_script.py.

tests/test_edit_strict_and_warnings.py (3)

6-7: LGTM: Proper import of shared test helper.

Good use of the centralized DummyContext from test_helpers.py.


70-77: LGTM: Consistent registry-based tool discovery.

The dynamic tool registration pattern is correctly implemented and aligns with the PR's test infrastructure improvements.


88-89: LGTM: Correct module-level patching.

Patching unity_connection.send_command_with_retry enables reliable monkeypatching as intended by the production code changes.

Also applies to: 113-114

UnityMcpBridge/UnityMcpServer~/src/tools/manage_script.py (1)

9-9: The review comment's premise is incorrect. Both UnityMcpBridge and MCPForUnity directories are maintained in parallel and independently.

The script results confirm:

  • manage_script.py exists in both /UnityMcpBridge/ and /MCPForUnity/ as separate implementations
  • Both directories are treated equally in test collection (both ignored together)
  • No cross-imports exist between them; each is self-contained
  • "Deprecated" references in UnityMcpBridge files refer to specific functionality (e.g., line 442 describes the tool as a "compatibility router for legacy script operations"), not directory-level deprecation

The PR description "removes deprecated UnityMcpBridge paths" is misleading. It likely means removing deprecated functionality within UnityMcpBridge (like legacy script operations), not removing the UnityMcpBridge directory itself. Updating manage_script.py in that directory is appropriate if the goal is to refactor or clean up its deprecated features while keeping both implementations maintained.

Likely an incorrect or invalid review comment.

tests/test_resources_api.py (2)

44-44: LGTM: Correct usage of shared test helper.

This file correctly imports DummyContext from tests.test_helpers, which is the intended pattern for sharing test utilities across the test suite.


83-90: LGTM: Proper event loop management.

Creating a dedicated event loop per test call and ensuring cleanup in the finally block is good practice for async testing isolation.

tests/test_telemetry_subaction.py (1)

4-43: LGTM: Isolated telemetry decorator testing.

The dynamic import setup with minimal stubs is appropriate for testing telemetry_decorator in isolation without file I/O dependencies. The attribute guards at lines 33-42 ensure monkeypatch targets exist even if not exported, which prevents test failures.

tests/conftest.py (1)

9-28: LGTM: Robust test collection configuration.

The combination of collect_ignore, collect_ignore_glob, and pytest_ignore_collect provides comprehensive exclusion of src directories to prevent duplicate-package import conflicts. Path normalization at line 22 handles cross-platform differences correctly.

Replace 7 duplicate DummyContext class definitions with imports from tests.test_helpers.
This follows DRY principles and ensures consistency across the test suite.
Copy link
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

♻️ Duplicate comments (1)
tests/test_telemetry_queue_worker.py (1)

82-84: Timeout relaxation partially addresses past review concerns.

The updated comment on line 83 acknowledging "thread scheduling variance in CI/local environments" is an improvement over the previous version. However, the 150% increase in timeout (80ms → 200ms) is still significant.

As noted in the past review, consider:

  • Was this increase based on observed test failures in CI, or is it a proactive buffer?
  • Could there be actual performance degradation that should be investigated rather than hidden by a larger timeout?
  • The past review suggested documenting the specific conditions that justify this threshold

If this increase resolves observed flakiness, consider adding that context (e.g., "Based on 10 CI runs, max observed time was 150ms").

🧹 Nitpick comments (1)
tests/test_telemetry_queue_worker.py (1)

33-36: Improve documentation for the intentional but confusing module stubbing strategy.

The pattern is now clear: the stub prevents normal imports while the real module is loaded separately with CWD manipulation (to support get_package_version()'s relative path to pyproject.toml, which is called at module import time).

However, the current comments are misleading. Line 46's comment "it will reuse stubbed helpers" is unclear—the real module defines its own get_package_version(), not reusing the stub. The stub's purpose (isolating the real module from normal import paths) isn't obvious from the code.

Recommendation:
Replace the comments on lines 33–36 and 46 to clearly explain this isolation pattern and why it's necessary. For example:

  • Lines 33–36: Document that the stub prevents normal imports of telemetry (avoiding side effects)
  • Lines 46–52: Explain that CWD manipulation is required because the real telemetry module calls get_package_version() at import time, which opens pyproject.toml via a relative path

Alternatively, consider simplifying by mocking only the necessary parts (e.g., get_package_version) where it's actually used, rather than pre-registering a stub module.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8cdcda3 and a607041.

📒 Files selected for processing (2)
  • tests/test_resources_api.py (4 hunks)
  • tests/test_telemetry_queue_worker.py (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
tests/test_telemetry_queue_worker.py (1)
MCPForUnity/UnityMcpServer~/src/telemetry.py (1)
  • get_package_version (39-46)
tests/test_resources_api.py (4)
MCPForUnity/UnityMcpServer~/src/telemetry.py (6)
  • MilestoneType (65-73)
  • record_resource_usage (454-472)
  • record_tool_usage (425-451)
  • record_milestone (271-293)
  • record_milestone (420-422)
  • get_package_version (39-46)
MCPForUnity/UnityMcpServer~/src/telemetry_decorator.py (1)
  • telemetry_tool (17-107)
tests/test_helpers.py (1)
  • DummyContext (1-10)
MCPForUnity/UnityMcpServer~/src/tools/resource_tools.py (1)
  • list_resources (137-186)
🔇 Additional comments (5)
tests/test_resources_api.py (5)

8-9: LGTM! Path consolidation aligns with PR objectives.

The SRC path update to MCPForUnity correctly reflects the consolidation effort mentioned in the PR summary, removing deprecated UnityMcpBridge references.


11-31: Well-designed test isolation.

The telemetry stub modules effectively prevent file I/O during tests while providing all necessary no-op implementations. This aligns with the PR's goal of making telemetry opt-in with explicit configuration.


44-44: Good practice: module-level import for test helper.

Moving the DummyContext import to the top level improves code organization and aligns with the PR's effort to extract common test utilities.


47-60: LGTM! Registry-based tool discovery implemented correctly.

The fixture refactor successfully adopts the dynamic registry pattern mentioned in the PR summary. The filtering logic appropriately identifies resource-related tools, and the implementation is consistent with similar patterns in other test files.


83-86: Correct modernization: asyncio.run() is the recommended approach.

The change from asyncio.get_event_loop().run_until_complete() to asyncio.run() is actually the correct modern Python practice (Python 3.7+). While asyncio.run() creates a new event loop for each call, this provides clean isolation between test cases and prevents loop state pollution—which is exactly what you want in tests. The overhead is negligible and the benefits (simpler code, better isolation) outweigh any performance concerns.

Also applies to: 99-101

Comment on lines 46 to 52
# Load real telemetry on top of stub (it will reuse stubbed helpers)
_prev_cwd = os.getcwd()
os.chdir(str(SRC))
try:
telemetry = _load_module(SRC / "telemetry.py", "telemetry_mod")
finally:
os.chdir(_prev_cwd)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Avoid CWD manipulation in test setup; consider mocking or fixing the source.

Changing the current working directory to load the telemetry module is fragile and can cause issues:

  • Side effects: If tests run concurrently or if other code depends on CWD, this can cause flakiness
  • Design smell: The need for CWD manipulation indicates that get_package_version() in telemetry.py uses a relative path to open pyproject.toml, which is not robust
  • Maintenance burden: Future changes to telemetry module imports or dependencies may break unexpectedly

Recommendations:

  1. Preferred: Mock get_package_version directly to return a test value without file I/O
  2. Fix the source code to use __file__ or accept a base directory parameter for locating pyproject.toml
  3. If CWD change is unavoidable, document specifically why it's necessary and what breaks without it

Example mock approach:

-# Load real telemetry on top of stub (it will reuse stubbed helpers)
-_prev_cwd = os.getcwd()
-os.chdir(str(SRC))
-try:
-    telemetry = _load_module(SRC / "telemetry.py", "telemetry_mod")
-finally:
-    os.chdir(_prev_cwd)
+# Load real telemetry module
+telemetry = _load_module(SRC / "telemetry.py", "telemetry_mod")
+# Mock get_package_version to avoid file I/O dependency
+telemetry.get_package_version = lambda: "0.0.0"

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In tests/test_telemetry_queue_worker.py around lines 46-52, avoid changing the
process CWD to load telemetry.py; instead either mock get_package_version in the
test to return a deterministic value (use patch to replace
telemetry.get_package_version before importing/using the module) or change
telemetry.py to resolve pyproject.toml relative to its own file (use __file__ or
accept a base_dir parameter) and update the test to import normally; remove the
os.chdir/_prev_cwd block and replace it with the mock or source fix to eliminate
fragile CWD manipulation.

…s.py

Dead code cleanup - function was no longer used after refactoring to dynamic tool registration.
Clarify why os.chdir() is necessary: telemetry.py calls get_package_version()
at module load time, which reads pyproject.toml using a relative path.
Acknowledges the fragility while explaining why it's currently required.
@dsarno dsarno merged commit 0397887 into CoplayDev:main Oct 21, 2025
1 check passed
@dsarno dsarno deleted the chore/pytest-harness-tests-only branch October 24, 2025 17:40
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