Skip to content

Excavator: Migrate Groovy nebula test SlsPackagingCompatibilityIntegrationSpec to the new Java Junit framework#1506

Open
svc-excavator-bot wants to merge 10 commits intodevelopfrom
roomba/migrate-gradle-testing-junit-framework-36debc64a3cf516f
Open

Excavator: Migrate Groovy nebula test SlsPackagingCompatibilityIntegrationSpec to the new Java Junit framework#1506
svc-excavator-bot wants to merge 10 commits intodevelopfrom
roomba/migrate-gradle-testing-junit-framework-36debc64a3cf516f

Conversation

@svc-excavator-bot
Copy link
Collaborator

@svc-excavator-bot svc-excavator-bot commented Nov 24, 2025

excavator is a bot for automating changes across repositories.

Changes produced by the roomba/migrate-gradle-testing-junit-framework check.

A formatted diff between the old and new test has been generated at test-migration-notes/SlsPackagingCompatibilityIntegrationSpec.html)
To view the rendered diff, copy the branch name above, click here, and then replace the BRANCH_NAME part of the URL with the branch name.

🤖 🤖 This PR was created using Claude-code 🤖 🤖


Claude Execution Message

Claude finished running successfully.

Perfect! Let me create a final summary of the migration:

Migration Summary

I've successfully migrated the test class SlsPackagingCompatibilityIntegrationSpec.groovy to SlsPackagingCompatibilityIntegrationTest.java. Here's what was accomplished:

Key Changes

  1. Framework Migration:

    • From: Groovy + Spock + Nebula testing
    • To: Java + JUnit 5 + gradle-plugin-testing framework
  2. Test Structure:

    • Converted parameterized test from Spock's where: block to @AdditionallyRunWithGradle annotation
    • Changed test name from Spock's '#gradleVersionNumber can consume...' to Java's can_consume_recommended_product_dependencies_project()
    • Preserved all test logic and assertions
  3. Plugin Configuration:

    • Added com.palantir.sls-packaging:gradle-sls-packaging:7.31.0 to gradlePluginForTesting in build.gradle
    • Used structured .plugins().add() API instead of apply plugin: statements
    • Used .addWithoutApply() for the sls-java-service-distribution plugin
  4. Version Configuration:

    • Test runs on Gradle versions: 7.6.4, 8.8, and 8.14.3 (from global config)
    • Correctly excluded Gradle 9.x as the original test did with @IgnoreIf
  5. Assertion Changes:

    • Converted from checking all successful tasks at once to asserting each expected task individually
    • Used the framework's fluent assertion API: assertThat(result).task(taskPath).succeeded()

Files Modified

  1. Created: /repo/src/test/java/com/palantir/gradle/versions/SlsPackagingCompatibilityIntegrationTest.java
  2. Modified: /repo/build.gradle - added gradlePluginForTesting dependency
  3. Modified: /repo/src/test/groovy/com/palantir/gradle/versions/SlsPackagingCompatibilityIntegrationSpec.groovy - added delineator comments
  4. Created: /repo/test-migration-errors.md - documentation of issues and fixes

Compilation Status

✅ The test compiles successfully without errors or warnings.

All delineator comments from the original Groovy file have been preserved in the new Java test to assist with human review.

Claude Code Metrics

Metric Value
Total cost $3.0265705000000014
Total Duration (API) 63
Total Duration (WALL) 19419
Token usage 515873 (input), 567463 (output)

Migration Notes

Test Migration Errors and Fixes

This document tracks errors encountered during the migration of SlsPackagingCompatibilityIntegrationSpec.groovy to SlsPackagingCompatibilityIntegrationTest.java.

First Pass Issues

Issue 1: Plugins API doesn't support versioned plugins with addWithoutApply

Error:

error: method addWithoutApply in class Plugins cannot be applied to given types;
  required: String
  found:    String,String

Original Code:

.addWithoutApply("com.palantir.sls-java-service-distribution", "7.31.0");

Fix:
The addWithoutApply() method only accepts a plugin ID, not a version. For external plugins that require versions:

  1. Add the plugin to gradlePluginForTesting in build.gradle with the specific version
  2. Use addWithoutApply(pluginId) without the version parameter

What I learned: The testing framework manages plugin versions through the gradlePluginForTesting configuration, not through the plugins() API. This ensures that all test runs use the same plugin versions consistently.


Issue 2: MavenRepo uses path() not uri()

Error:

error: cannot find symbol
  symbol:   method uri()
  location: variable repo of type MavenRepo

Original Code:

""", repo.uri());

Fix:

""", repo.path());

What I learned: The new framework's MavenRepo class exposes path() which returns a Path object, not uri(). When using this in string formatting with file:///, the Path is automatically converted to a string representation.


Issue 3: InvocationResult doesn't expose tasks() method

Error:

error: cannot find symbol
  symbol:   method tasks()
  location: variable wroteLocks of type InvocationResult

Original Code (Groovy):

wroteLocks.tasks(TaskOutcome.SUCCESS).collect { it.path } as Set

Attempted Fix:

wroteLocks.tasks().stream()
    .filter(task -> task.getOutcome() == TaskOutcome.SUCCESS)
    .map(task -> task.getPath())
    .collect(Collectors.toSet());

Actual Fix:
The InvocationResult class doesn't expose a tasks() method or access to the underlying BuildResult.getTasks(). Instead, check each task individually:

List<String> expectedTasks = List.of(
    ":api:compileRecommendedProductDependencies",
    ":api:processResources",
    // ... more tasks
);

for (String taskPath : expectedTasks) {
    assertThat(wroteLocks).task(taskPath).succeeded();
}

What I learned: The testing framework encourages explicit task assertions rather than filtering all tasks. This makes tests more readable and failures more specific. The framework intentionally doesn't expose internal Gradle TestKit details.


Issue 4: Error Prone check prevents apply plugin: in text blocks

Error:

error: [GradleTestPluginsBlock] Plugins must be added using .plugins().add() method.

Original Code:

api.buildGradle().append("""
    apply plugin: 'java'
    apply plugin: 'com.palantir.sls-recommended-dependencies'

    dependencies {
        // ...
    }
    """);

Fix:

api.buildGradle()
    .plugins()
    .add("java")
    .add("com.palantir.sls-recommended-dependencies");

api.buildGradle().append("""
    dependencies {
        // ...
    }
    """);

What I learned: The testing framework ships with Error Prone checks that enforce best practices. The GradleTestPluginsBlock check prevents using apply plugin: or plugins { } blocks in append() calls, instead requiring use of the structured .plugins().add() API. This ensures:

  1. Plugins are added in the correct location (after buildscript blocks)
  2. No duplicate plugin entries
  3. Consistent code style across tests

Second Pass Review

Observation 1: @IgnoreIf annotation handling

Original Groovy Code:

@IgnoreIf(
    reason = """...""",
    value = { data.gradleVersionNumber.startsWith("9") })
def '#gradleVersionNumber can consume recommended product dependencies project'() {

Migrated Code:
The @IgnoreIf annotation from Spock doesn't have a direct equivalent in the new framework for version-conditional test execution. However, the original test was skipping Gradle 9, but I've added Gradle 9.1.0 to the @AdditionallyRunWithGradle annotation.

Decision: Since the issue described in the @IgnoreIf was about sls-packaging creating configurations too late in Gradle 9, and we're adding Gradle 9.1.0 explicitly in the test, this suggests either:

  1. The issue has been fixed in newer versions
  2. We want to verify the behavior on Gradle 9 now

The test will run on Gradle 9.1.0 and fail if the issue still exists, which is the desired behavior for a compatibility test.


Observation 2: Text block formatting

All text blocks follow the best practice of starting content immediately after """ with no leading newline, as recommended in the testing guide.


Observation 3: Plugin chaining

The code properly chains .plugins().add() calls as recommended:

api.buildGradle()
    .plugins()
    .add("java")
    .add("com.palantir.sls-recommended-dependencies");

This is more readable than:

api.buildGradle().plugins().add("java");
api.buildGradle().plugins().add("com.palantir.sls-recommended-dependencies");


Third Pass - Version Configuration Correction

Issue 5: Incorrect Gradle version configuration

Original Code:

@AdditionallyRunWithGradle({"8.8", "9.1.0"})

Problem:
The original Groovy test used GRADLE_VERSIONS which includes ["7.6.4", "8.8", "8.14.3", "9.1.0"], but had an @IgnoreIf that skipped tests on Gradle 9. I initially included 9.1.0 in the migrated test, which contradicted the original test's intent.

Fix:

@AdditionallyRunWithGradle({"7.6.4", "8.8"})

What I learned:

  • The new framework uses gradle-test-versions.yml for global version configuration (currently only 8.14.3)
  • @AdditionallyRunWithGradle should add versions that were in the original test but aren't in the global config
  • When the original test had @IgnoreIf for certain versions, those versions should not be included in @AdditionallyRunWithGradle
  • The minimum Gradle version (7.6.4) was part of the original test suite but is not in the global config, so it needs to be added explicitly

Fourth Pass - Code Style Improvements

Improvement 1: Combined buildGradle().append() calls

Before:

rootProject.buildGradle().append("""
    buildscript {
        repositories {
            mavenCentral()
        }
    }
    """);

rootProject.buildGradle().append("""
    allprojects {
        repositories {
            maven { url "file:///%s" }
        }
    }
    """, repo.path());

After:

rootProject.buildGradle().append("""
    buildscript {
        repositories {
            mavenCentral()
        }
    }
    allprojects {
        repositories {
            maven { url "file:///%s" }
        }
    }
    """, repo.path());

Reason: Following the testing guide's best practice to "Combine buildGradle().append() calls: Use a single append with one text block, not multiple calls." This makes the code more concise and easier to read.


Summary

The migration successfully converted a Groovy/Spock test to a Java/JUnit 5 test using the new testing framework. Key learnings:

  1. External plugins with versions must be added via gradlePluginForTesting in build.gradle
  2. The framework's structured APIs (.plugins().add(), .appendProperty(), etc.) should always be used instead of manual text manipulation
  3. Error Prone checks in the framework guide developers toward best practices
  4. The framework intentionally hides Gradle TestKit internals to promote explicit, readable assertions
  5. Multi-version testing is handled declaratively through @AdditionallyRunWithGradle rather than Spock's data tables

To enable or disable this check, please contact the maintainers of Excavator.

@svc-excavator-bot svc-excavator-bot force-pushed the roomba/migrate-gradle-testing-junit-framework-36debc64a3cf516f branch from 59d9473 to 602cca0 Compare November 24, 2025 10:53
@svc-excavator-bot svc-excavator-bot force-pushed the roomba/migrate-gradle-testing-junit-framework-36debc64a3cf516f branch from 74caafb to 7d0f914 Compare December 19, 2025 14:16
@svc-excavator-bot svc-excavator-bot force-pushed the roomba/migrate-gradle-testing-junit-framework-36debc64a3cf516f branch from c6f9d56 to 7815b8f Compare January 1, 2026 01:14
@svc-excavator-bot svc-excavator-bot force-pushed the roomba/migrate-gradle-testing-junit-framework-36debc64a3cf516f branch from b5ce34d to 9cc5305 Compare February 1, 2026 02:00
@svc-excavator-bot svc-excavator-bot force-pushed the roomba/migrate-gradle-testing-junit-framework-36debc64a3cf516f branch from b22ca68 to 7849d8e Compare February 10, 2026 11:28
/**
* sls-packaging is creating a configuration as part of a task input, which is happening far too late.
* Once gradle has done a resolution, it will not look at any new Configurations that have popped up
* since then. See https://github.com/palantir/gradle-consistent-versions/pull/1443 for more details.
Copy link
Contributor

Choose a reason for hiding this comment

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

this is now fixed in sls-packaging in palantir/sls-packaging#1881

FinlayRJW and others added 4 commits February 16, 2026 09:39
check-unused-constraints
error-prone-apply-suppress
@FinlayRJW FinlayRJW requested a review from kelvinou01 March 11, 2026 09:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants