Summary
Add a Gradle Tooling API (GTA) based test event pipeline for Delegate Test to Gradle, so Gradle test delegation can provide real-time, structured test results without depending on BSP project import state or JUnit XML parsing as the primary mechanism.
The current implementation uses a conservative BSP-first strategy and falls back to direct Gradle execution plus JUnit XML parsing when BSP test delegation is unavailable. That fallback unblocks non-BSP / Buildship / failed-BSP-import projects, but XML is batch-oriented and cannot provide the same real-time or structured experience as an event stream.
Goals
- Make Gradle delegated test execution independent from BSP import state.
- Provide real-time test status updates for non-BSP projects.
- Use Gradle Tooling API test progress events as the long-term default event source.
- Preserve the current XML fallback as a compatibility path while the GTA implementation matures.
- Avoid re-running tests or hiding real build/test failures when a primary path fails after execution starts.
Non-goals
- Do not remove the current BSP path in the first iteration.
- Do not remove the XML fallback until the GTA path is proven stable.
- Do not attempt to fully model every JUnit/TestNG/dynamic-test edge case in the first milestone.
- Do not introduce behavior that retries tests after a real test/build failure.
Proposed execution strategy
Long term, the test delegation engine should become:
Delegate Test to Gradle
-> GTA test event stream when supported
-> XML fallback when GTA is unavailable or unsupported
During migration, a safer staged strategy can be:
Delegate Test to Gradle
-> existing BSP path if available
-> GTA test event path when BSP is unavailable
-> XML fallback when neither BSP nor GTA event streaming is available
Milestones
1. Design and capability investigation
- Identify where the Gradle server invokes Gradle Tooling API today.
- Confirm how to register test progress listeners during delegated test builds.
- Define the minimum event model needed by the extension:
- event kind:
started, finished, output
- descriptor id and parent descriptor id
- project path and task path
- class name, method name, display name
- result state, duration, message, stack trace
- Decide how capability detection/versioning should work so older servers/extensions degrade safely.
- Confirm how cancellation and debug attach should interact with the GTA path.
2. Implement GTA event streaming end to end
- Add the server-side Gradle Tooling API test listener.
- Convert Gradle test descriptors/results into the new gRPC event model.
- Include project/task metadata to avoid multi-project result collisions.
- Add extension-side mapping from GTA events to
vscode-java-test status events.
- Preserve pending-item finalization so requested tests never remain stuck in
Running.
- Keep XML fallback for cases where GTA events are unavailable or unsupported.
Initial scope should cover:
- test started
- test passed
- test failed
- test errored
- test skipped
- duration and basic failure message/stack trace
Follow-up enhancements can add:
- per-test stdout/stderr where Gradle supports
TestOutputEvent
- structured failure cause chains where Gradle supports them
- richer nested/dynamic test hierarchy
3. Mapping, debug, and compatibility hardening
- Define stable test id mapping rules for:
- class-level runs
- method-level runs
- parameterized test invocations
- nested classes
- dynamic tests / synthetic children
- multi-project builds with identical fully-qualified class names
- Prefer mapping results back to explicitly requested test ids.
- Reuse the existing debug attach flow initially.
- Prevent multiple Gradle
Test tasks from racing on the same debug port.
- Avoid falling back to XML after a GTA run has already started executing tests, unless the failure is a known capability/precondition failure before execution.
4. Test coverage and rollout
- Add server tests for Gradle test event conversion.
- Add extension unit tests for GTA event to
TestRunner event mapping.
- Add integration tests for non-BSP project test delegation.
- Cover multi-project, parameterized, nested, skipped, failed, errored, cancellation, and build-failure cases where practical.
- Roll out behind capability detection first.
- Keep XML fallback enabled during initial rollout.
- Switch to GTA-first only after tests and dogfooding show stable behavior.
Acceptance criteria
- Non-BSP Gradle projects can use
Delegate Test to Gradle with real-time test status updates.
- BSP-imported projects do not regress.
- Test failures are reported without duplicate execution.
- Requested test items always receive a terminal state.
- Multi-project builds do not mix results between projects with identical class names.
- XML fallback remains available when GTA test events are not supported.
- CI includes meaningful unit and integration coverage for the GTA path.
Related context
- Current mitigation: BSP-first delegation with XML fallback when BSP is unavailable.
- Related issues:
Summary
Add a Gradle Tooling API (GTA) based test event pipeline for
Delegate Test to Gradle, so Gradle test delegation can provide real-time, structured test results without depending on BSP project import state or JUnit XML parsing as the primary mechanism.The current implementation uses a conservative BSP-first strategy and falls back to direct Gradle execution plus JUnit XML parsing when BSP test delegation is unavailable. That fallback unblocks non-BSP / Buildship / failed-BSP-import projects, but XML is batch-oriented and cannot provide the same real-time or structured experience as an event stream.
Goals
Non-goals
Proposed execution strategy
Long term, the test delegation engine should become:
During migration, a safer staged strategy can be:
Milestones
1. Design and capability investigation
started,finished,output2. Implement GTA event streaming end to end
vscode-java-teststatus events.Running.Initial scope should cover:
Follow-up enhancements can add:
TestOutputEvent3. Mapping, debug, and compatibility hardening
Testtasks from racing on the same debug port.4. Test coverage and rollout
TestRunnerevent mapping.Acceptance criteria
Delegate Test to Gradlewith real-time test status updates.Related context