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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions