Skip to content

test: add unit tests for utility modules#309

Open
Tyrrnien81 wants to merge 2 commits intorobotmcp:developfrom
Tyrrnien81:test/add-utils-unit-tests
Open

test: add unit tests for utility modules#309
Tyrrnien81 wants to merge 2 commits intorobotmcp:developfrom
Tyrrnien81:test/add-utils-unit-tests

Conversation

@Tyrrnien81
Copy link
Copy Markdown

Summary

  • Add tests/unit/ directory with unit tests for ros_mcp/utils/
  • Cover response.py, config_utils.py, network_utils.py
  • All network operations are mocked — no real connections needed
  • Total: 47 test cases covering all code branches and edge cases

Motivation

Currently, the only tests in tests/ verify package installation (Docker-based). There are no tests for the core utility logic that every tool depends on. This PR adds foundational unit test infrastructure.

Changes

File Purpose
tests/unit/__init__.py Package init
tests/unit/conftest.py Shared fixtures (rosbridge responses, robot YAML configs)
tests/unit/test_response.py 20 tests for response validation functions
tests/unit/test_config_utils.py 12 tests for robot config loading and listing
tests/unit/test_network_utils.py 15 tests for DNS resolution and ping diagnostics

Test Plan

Closes #308

Copy link
Copy Markdown

@samkwak188 samkwak188 left a comment

Choose a reason for hiding this comment

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

I read all five files under tests/unit/. The suite cleanly targets ros_mcp/utils (response, config_utils, network_utils) with shared fixtures in conftest.py and mocked I/O so nothing requires a live network or robot. Structure and naming look consistent with pytest usage; author’s test plan (pytest tests/unit/, ruff) matches the intent for #308.

Copy link
Copy Markdown

@raphy0316 raphy0316 left a comment

Choose a reason for hiding this comment

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

Looks great overall — test structure and coverage are really solid
Nice use of mocking and good edge case handling.

Just a couple small thoughts:

  • Might be safer to use exact matches instead of substring checks for status
  • test_with_real_robot_specs feels a bit like an integration test — maybe worth separating or marking later
  • Monkeypatching __file__ works, but could be cleaner with injection if we refactor in the future

Otherwise, looks good to me

@stex2005
Copy link
Copy Markdown
Collaborator

stex2005 commented Apr 7, 2026

Thanks for putting this together, @Tyrrnien81! Great to see unit test infrastructure being built out, and the test organization is clean.

I've been working on the integration test suite (PRs #276-#281, #316, #321) and wanted to share some thoughts on how these two efforts overlap and where to focus energy.

What's most valuable here

The config_utils tests are the highlight — load_robot_config, get_verified_robot_spec_util, get_verified_robots_list_util have zero coverage elsewhere, and the tmp_path/monkeypatch approach is the right way to test them. That said, these are tightly coupled to the folder structure (Path(__file__).parent.parent.parent / "robot_specifications"), so the monkeypatching is inherently fragile. Worth keeping, but worth acknowledging in comments.

Where there's overlap

The response.py and network_utils.py tests overlap significantly with the integration test suite:

  • _check_response and _safe_get_values are 3-line utility functions. The integration tests exercise them implicitly on every tool call (get_nodes, get_services, subscribe_once, etc.) — across 4 ROS distros with real rosbridge responses. Testing them 13 different ways with None/empty-dict/string/list inputs is testing Python dict behavior more than application logic.

  • ping_ip_and_port has 12 fully-mocked tests, but tests/integration/test_connection.py already tests ping_rosbridge, ping_closed_port, ping_multiple_targets against real sockets — which catches real bugs that mocks can't.

  • _resolve_dns tests that "127.0.0.1" returns itself — that's testing Python's ipaddress module, not our code.

Suggestion

Would you consider splitting this into smaller PRs?

  1. PR 1: test_config_utils.py + conftest.py + __init__.py — this is the valuable, non-overlapping part. Merge it first.
  2. PR 2 (optional): test_response.py — trimmed down to just the edge cases that integration tests don't cover (if any remain after review).
  3. Skip test_network_utils.py — the integration tests cover ping_ip_and_port better with real sockets, and _resolve_dns is a thin wrapper around stdlib.

This keeps the test suite lean and avoids maintaining mock-heavy tests that duplicate what the integration suite already validates end-to-end.

Again, appreciate the effort here — especially the clean pytest structure and proper use of tmp_path fixtures! 🙏

Copy link
Copy Markdown
Collaborator

@stex2005 stex2005 left a comment

Choose a reason for hiding this comment

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

as per the comment above.

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.

4 participants