Skip to content

[Feature] Add Gradle Tooling API test event stream for delegated Gradle tests #1817

@wenytang-ms

Description

@wenytang-ms

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions