Skip to content

Conversation

@kou-123
Copy link

@kou-123 kou-123 commented Dec 31, 2025

Description

Add unit tests for utils/client_info.py which previously had no test coverage.

Changes

  • Add tests/test_client_info.py with comprehensive tests for:
    • get_friendly_name() - client name mapping
    • format_client_info() - info formatting
    • get_client_info_from_context() - context extraction
    • get_cached_client_info() - caching
    • get_client_friendly_name() - convenience function
    • log_client_info() - logging

Type of Change

  • Bug fix
  • New feature
  • Test addition

Checklist

  • Tests added
  • Self-review completed

Add comprehensive unit tests for the client_info utility module:
- TestGetFriendlyName: client name to friendly name mapping
- TestFormatClientInfo: client info formatting
- TestGetClientInfoFromContext: context extraction with edge cases
- TestGetCachedClientInfo: caching behavior
- TestGetClientFriendlyName: convenience function
- TestLogClientInfo: logging functionality

This module previously had no test coverage.
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @kou-123, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the test coverage for the utils/client_info.py module by introducing a new, dedicated unit test file. The primary goal is to ensure the reliability and correctness of functions responsible for identifying, formatting, and caching client-specific information within the application. This addition helps prevent regressions and provides confidence in the client identification logic.

Highlights

  • New Test File: A new test file, tests/test_client_info.py, has been added to introduce comprehensive unit test coverage for the utils/client_info module.
  • Comprehensive Function Testing: Extensive tests have been implemented for get_friendly_name(), format_client_info(), get_client_info_from_context(), get_cached_client_info(), get_client_friendly_name(), and log_client_info() to ensure their correctness and robustness.
  • Client Name Mapping Validation: Tests for get_friendly_name() cover various client name variants (e.g., Claude, Gemini, Cursor, VS Code, Codeium, GitHub Copilot), including handling of empty, None, unknown, case-insensitive, and partial matches.
  • Client Info Formatting Validation: Tests for format_client_info() verify proper formatting of client information, considering cases with and without friendly names, versions, and fallback to default names.
  • Context Extraction and Caching Validation: Tests for get_client_info_from_context() validate extraction from server request contexts, including scenarios with missing context components, successful extraction, caching behavior, and handling of missing version information. get_cached_client_info() and get_client_friendly_name() tests confirm correct retrieval of cached data.
  • Logging Behavior Validation: Tests for log_client_info() ensure that client information is logged correctly when available and that appropriate debug messages are logged when extraction fails.
  • Constant Validation: The CLIENT_NAME_MAPPINGS constant is tested to ensure it is not empty and contains string values, and that DEFAULT_FRIENDLY_NAME is a valid string.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request adds a comprehensive set of unit tests for the utils/client_info.py module, which is a great addition for improving code quality and reliability. The tests cover many edge cases and scenarios. My review includes suggestions to further improve the tests by using pytest.mark.parametrize for better test reporting, refactoring duplicated and brittle test setup code into a more robust pytest fixture, and adding a missing test case to ensure full coverage of the logic.

Comment on lines 159 to 163
def setup_method(self):
"""Reset the cache before each test."""
import utils.client_info as client_info_module

client_info_module._client_info_cache = None
Copy link
Contributor

Choose a reason for hiding this comment

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

high

Directly modifying the private _client_info_cache variable from another module makes these tests brittle, as they are tightly coupled to the implementation details of utils.client_info. A more robust approach is to use pytest's monkeypatch fixture to control the module's state.

This setup_method is also duplicated across four test classes. This can be consolidated into a single autouse fixture at the module level to reduce code duplication.

Consider adding this fixture to the top of your file and removing the duplicated setup_method from each class:

@pytest.fixture(autouse=True)
def _reset_cache(monkeypatch):
    """Fixture to reset the client info cache before each test."""
    monkeypatch.setattr("utils.client_info._client_info_cache", None)

Comment on lines 36 to 51
def test_claude_variants(self):
"""Various Claude client names should return 'Claude'."""
claude_names = [
"claude-ai",
"Claude-AI",
"CLAUDE-AI",
"claude",
"Claude",
"claude-desktop",
"Claude-Desktop",
"claude-code",
"anthropic",
"Anthropic-Client",
]
for name in claude_names:
assert get_friendly_name(name) == "Claude", f"Failed for: {name}"
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This test and others like test_gemini_variants and test_unknown_client_returns_default use a for loop over a list of test cases. While this works, it's better to use pytest.mark.parametrize. This decorator turns each item in your list into a separate test case, which provides clearer test reports. If one case fails, pytest will tell you exactly which input caused the failure, rather than failing the entire test method.

Suggested change
def test_claude_variants(self):
"""Various Claude client names should return 'Claude'."""
claude_names = [
"claude-ai",
"Claude-AI",
"CLAUDE-AI",
"claude",
"Claude",
"claude-desktop",
"Claude-Desktop",
"claude-code",
"anthropic",
"Anthropic-Client",
]
for name in claude_names:
assert get_friendly_name(name) == "Claude", f"Failed for: {name}"
@pytest.mark.parametrize(
"name",
[
"claude-ai",
"Claude-AI",
"CLAUDE-AI",
"claude",
"Claude",
"claude-desktop",
"Claude-Desktop",
"claude-code",
"anthropic",
"Anthropic-Client",
],
)
def test_claude_variants(self, name):
"""Various Claude client names should return 'Claude'."""
assert get_friendly_name(name) == "Claude"



class TestGetClientInfoFromContext:
"""Tests for get_client_info_from_context function."""
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The test coverage for get_client_info_from_context is good, but it appears to be missing a case. You test for _client_params being missing, but not for the case where _client_params exists but does not have the clientInfo attribute. Adding a test for this scenario would make the test suite more complete.

You could add a test like this to the TestGetClientInfoFromContext class:

def test_client_params_without_client_info(self):
    """Context with _client_params but no clientInfo should return None."""
    server = MagicMock()
    # Configure mock up to _client_params
    server.request_context.session._client_params = MagicMock(spec=[])  # No clientInfo attribute
    assert get_client_info_from_context(server) is None


def test_caching_behavior(self):
"""Should cache the result and return cached value on subsequent calls."""
import utils.client_info as client_info_module
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The import utils.client_info as client_info_module statement is repeated inside several methods (here and in setup_method, test_extraction_with_missing_version, etc.). Per PEP 8, imports should be placed at the top of the file. This improves code readability and avoids re-importing the same module multiple times. Please move this import to the top-level of the module.

"""Should handle missing version attribute."""
import utils.client_info as client_info_module

client_info_module._client_info_cache = None
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The setup_method for this test class already resets the _client_info_cache to None before each test runs. This line is therefore redundant and can be removed. Keeping it might cause confusion about whether the setup method is working as expected.

@kou-123
Copy link
Author

kou-123 commented Dec 31, 2025

Thanks for the review! I've addressed all the feedback:

  • Moved import utils.client_info to top level (PEP 8)
  • Used @pytest.mark.parametrize instead of for loops
  • Added autouse fixture to replace duplicated setup_method
  • Added test case for _client_params without clientInfo
  • Removed redundant monkeypatch.setattr call

@kou-123
Copy link
Author

kou-123 commented Dec 31, 2025

Thanks for the review! I've addressed all the feedback:

  • Moved import utils.client_info to top level (PEP 8)
  • Used @pytest.mark.parametrize instead of for loops
  • Added autouse fixture to replace duplicated setup_method
  • Added test case for _client_params without clientInfo
  • Removed redundant monkeypatch.setattr call

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