Skip to content

Conversation

@ninjinkun
Copy link
Contributor

@ninjinkun ninjinkun commented May 22, 2025

In Junit5, nested classes are represented with $ likeOuterClass$InnerClass. One of our customers requested us to handle this case. I found we've already handled the case in the Gradle plugin. So, I copied the code to the Maven plugin and added a test case for it.

Summary by CodeRabbit

  • New Features
    • Improved handling of nested test class names in Maven and Gradle test reports, ensuring inner class suffixes are correctly processed during test recording.
  • Tests
    • Added new test cases and sample Maven test reports to verify the correct handling of nested class names in test recording workflows.
  • Chores
    • Updated dependency version constraints for the click package to ensure compatibility with Python versions above 3.6.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented May 22, 2025

"""

Walkthrough

The changes introduce explicit handling for Java nested test classes in Maven test report processing. A new function replaces static file mask logic, allowing dynamic report file input and custom class name normalization by stripping $ suffixes. Additional test data, a new Maven XML report, and a test case validate correct processing of nested class names in the test runner and its output.

Changes

File(s) Change Summary
launchable/test_runners/maven.py Replaced static record_tests assignment with a new function accepting multiple report paths and normalizing nested class names by stripping $ suffixes using junit5_nested_class_path_builder.
launchable/test_runners/gradle.py Refactored record_tests to use junit5_nested_class_path_builder utility for nested class name handling instead of inline function.
launchable/utils/java.py Added junit5_nested_class_path_builder utility function to wrap path builder and strip inner class names from JUnit 5 test paths.
tests/data/maven/record_test_result.json Added a new test case entry for a nested class to the events array in the JSON test results.
tests/data/maven/reports/TEST-nested.xml Added a new Maven Surefire XML report for a nested test class (InnerClass).
tests/test_runners/test_maven.py Added a test method to verify correct handling and normalization of nested class names during test recording.
setup.cfg Restricted the click package dependency version to <8.2 for Python versions above 3.6.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI
    participant MavenTestRunner
    participant PathBuilder
    participant CommonRecordTestImpls

    User->>CLI: launchable record tests <report files>
    CLI->>MavenTestRunner: record_tests(client, reports)
    MavenTestRunner->>PathBuilder: Override path_builder with junit5_nested_class_path_builder
    MavenTestRunner->>CommonRecordTestImpls: load_report_files(client, reports)
    CommonRecordTestImpls->>PathBuilder: Build normalized test paths (strip inner class names)
    CommonRecordTestImpls-->>MavenTestRunner: Processed test data
    MavenTestRunner-->>CLI: Complete recording
Loading

Poem

In Maven’s warren, tests abound,
Nested classes now are found.
With $-tails snipped, they hop in line,
Reports and XMLs combine.
A rabbit cheers this tidy feat—
Clean class names, oh what a treat!
🐇✨
"""

Note

⚡️ AI Code Reviews for VS Code, Cursor, Windsurf

CodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback.
Learn more here.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2cbfa64 and 6e5d832.

📒 Files selected for processing (1)
  • launchable/utils/java.py (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • launchable/utils/java.py
⏰ Context from checks skipped due to timeout of 90000ms (13)
  • GitHub Check: build (windows-latest, 3.6)
  • GitHub Check: build (windows-latest, 3.12)
  • GitHub Check: build (windows-latest, 3.11)
  • GitHub Check: build (windows-latest, 3.10)
  • GitHub Check: build (windows-latest, 3.9)
  • GitHub Check: build (windows-latest, 3.8)
  • GitHub Check: build (windows-latest, 3.7)
  • GitHub Check: build (ubuntu-22.04, 3.12)
  • GitHub Check: build (ubuntu-22.04, 3.11)
  • GitHub Check: build (ubuntu-22.04, 3.10)
  • GitHub Check: build (ubuntu-22.04, 3.9)
  • GitHub Check: build (ubuntu-22.04, 3.8)
  • GitHub Check: build (ubuntu-22.04, 3.7)
✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@ninjinkun ninjinkun requested a review from Copilot May 22, 2025 01:59
Copy link
Contributor

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 adds support for nested classes in the Maven plugin by modifying how test class names containing '$' are handled, ensuring that inner class names are removed during test recording.

  • Introduces a new test in tests/test_runners/test_maven.py for verifying nested class handling.
  • Updates the Maven plugin logic in launchable/test_runners/maven.py to strip inner class identifiers.
  • Adds a new test report (TEST-nested.xml) and updates the recorded test result (record_test_result.json) accordingly.

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
tests/test_runners/test_maven.py Added integration and unit tests for nested class logic
tests/data/maven/reports/TEST-nested.xml New test report to simulate nested class output
tests/data/maven/record_test_result.json Updated expected test results to reflect nested class fix
launchable/test_runners/maven.py Updated logic to handle nested class names in test paths

report_file: str) -> TestPath:
"""
With @Nested tests in JUnit 5, test class names have inner class names
like com.launchableinc.rocket_car_gradle.AppTest$InnerClass.
Copy link

Copilot AI May 22, 2025

Choose a reason for hiding this comment

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

Consider updating the sample class name in the docstring to match the Maven context, e.g., 'com.launchableinc.rocket_car_maven.NestedTest$InnerClass', for clarity and consistency.

Copilot uses AI. Check for mistakes.
@ninjinkun ninjinkun marked this pull request as ready for review May 22, 2025 02:14
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: 0

🧹 Nitpick comments (1)
tests/test_runners/test_maven.py (1)

132-174: Comprehensive test for nested class name handling

The test thoroughly covers both unit functionality and integration testing:

  1. It directly tests the path builder function that strips the $ suffix
  2. It verifies the complete CLI workflow with the actual nested class test report

The test structure is clean and well-documented with a clear explanation of what's being tested.

One minor suggestion for future improvements:

-        # Extract the implementation from maven.py directly
-        # This gets the implementation without going through the CLI/Click command
+        # Extract the core path builder logic for direct unit testing
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3b003a1 and 1531ba4.

📒 Files selected for processing (4)
  • launchable/test_runners/maven.py (2 hunks)
  • tests/data/maven/record_test_result.json (1 hunks)
  • tests/data/maven/reports/TEST-nested.xml (1 hunks)
  • tests/test_runners/test_maven.py (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
tests/test_runners/test_maven.py (1)
tests/cli_test_case.py (3)
  • CliTestCase (21-341)
  • cli (200-211)
  • assert_success (213-214)
⏰ Context from checks skipped due to timeout of 90000ms (13)
  • GitHub Check: build (windows-latest, 3.6)
  • GitHub Check: build (windows-latest, 3.12)
  • GitHub Check: build (windows-latest, 3.11)
  • GitHub Check: build (windows-latest, 3.10)
  • GitHub Check: build (windows-latest, 3.9)
  • GitHub Check: build (windows-latest, 3.8)
  • GitHub Check: build (windows-latest, 3.7)
  • GitHub Check: build (ubuntu-22.04, 3.12)
  • GitHub Check: build (ubuntu-22.04, 3.11)
  • GitHub Check: build (ubuntu-22.04, 3.10)
  • GitHub Check: build (ubuntu-22.04, 3.9)
  • GitHub Check: build (ubuntu-22.04, 3.8)
  • GitHub Check: build (ubuntu-22.04, 3.7)
🔇 Additional comments (4)
tests/data/maven/reports/TEST-nested.xml (1)

1-4: Well-structured test data for nested class testing

This XML file correctly represents a Maven Surefire test report for a nested/inner class in Java, using the standard $ notation in the class name. The file will be useful for testing the new functionality.

tests/data/maven/record_test_result.json (1)

21-38: Test data correctly represents the expected transformed output

This new test case entry correctly shows how the nested class name should appear in the final output - with the $InnerClass part removed from the class name, leaving only com.launchableinc.rocket_car_maven.NestedTest. This aligns with the implementation goal of stripping inner class suffixes.

launchable/test_runners/maven.py (2)

118-138: Well-implemented solution for handling nested class names

The implementation correctly:

  1. Replaces the static file mask with dynamic report file input
  2. Overrides the path builder to strip inner class suffixes after $
  3. Provides thorough documentation explaining the rationale

This approach properly handles JUnit 5 nested test classes while maintaining backward compatibility.


9-9:

Details

✅ Verification successful

Verify the relative import path change

The import path for testpath has changed from a relative import to a parent-level relative import. While this likely works in the current directory structure, verify that this change is intentional and doesn't indicate a deeper issue.


🏁 Script executed:

#!/bin/bash
# Check the directory structure to confirm the import path is correct
echo "Current directory structure:"
find launchable -type d | sort

echo "\nChecking for testpath.py location:"
find launchable -name "testpath.py"

Length of output: 428


Import path verified

The from ..testpath import TestPath statement in launchable/test_runners/maven.py correctly resolves to launchable/testpath.py based on the current directory structure. No changes are needed.

@ninjinkun ninjinkun requested a review from takanabe May 22, 2025 02:19
@takanabe
Copy link
Contributor

LGTM but I will involve another member just in case.

@takanabe takanabe requested a review from Konboi May 22, 2025 03:03
@launchable-app

This comment has been minimized.

@ninjinkun
Copy link
Contributor Author

I found the test failure to be caused by Click's breaking change since v8.2. I'm going to fix this issue on another PR.

@ninjinkun
Copy link
Contributor Author

To pass the test, I limited the Click version up to 8.1. I noted the issue #1006.

def record_tests(client, reports):
default_path_builder = client.path_builder

def path_builder(case: TestCase, suite: TestSuite,
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems this logic is same with the gradle one.

So, how about defining the function and use from the maven and the gradle profile like the nunit and dotnet?

def junit5_parse_func( ...)
   ...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks! I did it on 2cbfa64

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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 72d6428 and 2cbfa64.

📒 Files selected for processing (3)
  • launchable/test_runners/gradle.py (2 hunks)
  • launchable/test_runners/maven.py (2 hunks)
  • launchable/utils/java.py (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • launchable/test_runners/maven.py
🧰 Additional context used
🧬 Code Graph Analysis (2)
launchable/test_runners/gradle.py (1)
launchable/utils/java.py (2)
  • junit5_nested_class_path_builder (35-56)
  • path_builder (52-54)
launchable/utils/java.py (1)
launchable/test_runners/flutter.py (2)
  • TestCase (18-74)
  • TestSuite (77-85)
🪛 GitHub Actions: Python package
launchable/utils/java.py

[error] 35-35: Function "builtins.callable" is not valid as a type. Perhaps you meant "typing.Callable" instead of "callable"? (valid-type)


[error] 53-53: Type error: 'callable?' is not callable. (misc)

🔇 Additional comments (5)
launchable/utils/java.py (3)

5-7: LGTM - Clean imports for the new functionality.

The imports are correctly added to support the new utility function's type annotations and functionality.


36-51: Excellent documentation and clear purpose.

The docstring clearly explains the problem being solved (JUnit 5 nested classes with $ syntax) and why this approach was chosen. The explanation about Launchable CLI's inability to detect inner classes during subsetting provides good context.


52-56:

Details

✅ Verification successful

Logic looks correct but verify list comprehension assumptions.

The implementation correctly processes the test path by splitting class names at $ and taking only the outer class name. The logic preserves non-class items unchanged.

However, please verify that test_path is always a list of dictionaries with type and name keys as expected.


🏁 Script executed:

#!/bin/bash
# Description: Verify the structure of test_path objects returned by path builders
# Expected: TestPath should be a list of dictionaries with 'type' and 'name' keys

# Search for TestPath usage patterns and path_builder implementations
ast-grep --pattern 'def $_(case: $_, suite: $_, report_file: $_) -> TestPath:
  $$$'

# Search for TestPath type definition
rg -A 10 "class TestPath\|TestPath.*=" 

# Search for existing path_builder usage
rg -A 5 -B 5 "path_builder.*case.*suite"

Length of output: 23282


Approve Java path_builder logic

Verified that default_path_builder consistently returns a TestPath (i.e. a List[Dict] with "type" and "name" keys) across all runners, and the existing unit test in tests/test_runners/test_maven.py confirms correct stripping of nested-class suffixes after $. No further changes required.

🧰 Tools
🪛 GitHub Actions: Python package

[error] 53-53: Type error: 'callable?' is not callable. (misc)

launchable/test_runners/gradle.py (2)

6-6: LGTM - Clean import for the utility function.

The import correctly brings in the new utility function from the Java utils module.


112-112: Excellent refactoring to use centralized logic.

This change replaces the previously inline nested class handling with the centralized junit5_nested_class_path_builder utility. This is exactly the type of code consolidation mentioned in the PR objectives where functionality from the Gradle plugin was copied to Maven, and now both can share the same implementation.

The wrapper pattern preserves the existing behavior while adding nested class support.

@sonarqubecloud
Copy link

@ninjinkun ninjinkun requested a review from Konboi May 23, 2025 04:00
Copy link
Contributor

@Konboi Konboi left a comment

Choose a reason for hiding this comment

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

LGTM

@ninjinkun ninjinkun merged commit a4f4489 into main May 23, 2025
16 checks passed
@ninjinkun ninjinkun deleted the maven-java-nested-class branch May 23, 2025 04:50
@github-actions github-actions bot mentioned this pull request May 23, 2025
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