Excavator: Migrate Groovy nebula test ConsistentVersionsPluginIntegrationSpec to the new Java Junit framework
#1508
+17,433
−619
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 can be viewed here
🤖 🤖 This PR was created using Claude-code 🤖 🤖
Claude Execution Message
Claude finished running successfully.
Perfect! The migration is complete. Let me create a summary for you:
Migration Complete! 🎉
I've successfully migrated
ConsistentVersionsPluginIntegrationSpec.groovytoConsistentVersionsPluginIntegrationTest.java. Here's what was done:Files Created/Modified:
Modified:
src/test/groovy/com/palantir/gradle/versions/ConsistentVersionsPluginIntegrationSpec.groovy***DELINEATOR FOR REVIEW:) to help with human reviewCreated:
src/test/java/com/palantir/gradle/versions/ConsistentVersionsPluginIntegrationTest.java@GradlePluginTestsannotation for automatic multi-version testingCreated:
src/test/java/com/palantir/gradle/versions/MetadataFile.javaCreated:
test-migration-errors.mdKey Changes Made:
@GradlePluginTests(no manual parameterization needed).buildGradle().append(),.propertiesFile().appendProperty()).plugins().add()API instead ofapply plugin:stringsMavenRepoparameter injection withMavenArtifact.publish()SubProjectparameter injection with automatic registrationCompilation Status:
✅ BUILD SUCCESSFUL - The new test compiles without errors!
The migrated tests maintain all functionality from the original Groovy tests while following best practices for the new framework. The delineator comments in both files will help human reviewers compare the old and new implementations.
Claude Code Metrics
Migration Notes
Test Migration Errors and Learnings
This document tracks errors encountered and lessons learned during the migration of
ConsistentVersionsPluginIntegrationSpec.groovytoConsistentVersionsPluginIntegrationTest.java.Initial Migration Errors
1. Incorrect Import for
DirectoryandProjectFileError:
Resolution:
import com.palantir.gradle.testing.file.ProjectFile;to usecom.palantir.gradle.testing.files.gradle.GradleFileimport com.palantir.gradle.testing.project.Directory;toimport com.palantir.gradle.testing.files.Directory;Learning: The new framework has a different package structure for file-related classes. Directory is in
filespackage, notprojectpackage.2. Plugins API Return Type Confusion
Error:
Initial Approach: Tried to chain
.buildGradle()after.plugins().add()calls like:Resolution:
The
plugins().add()method returnsPlugins, not the build file. The correct pattern is:Learning: The Plugins API is separate from the build file API. To continue working with the build file after adding plugins, you need to call
buildGradle()again.3. Wrong Class Name for Build Gradle Files
Error:
Initial Attempt: Used
BuildGradleFileas the return type for helper method.Resolution: The correct interface is
GradleFile, notBuildGradleFile.Learning: The testing framework uses
GradleFileas the general interface for gradle files.4. BuildDir Access Pattern
Error:
Initial Attempt: Tried
rootProject.directory("foo").buildDir()Resolution:
buildDir()is available on SubProject/RootProject, not on arbitrary Directory:Learning: Only GradleProject types (RootProject, SubProject) have
buildDir()method, not arbitrary Directory instances.5. AssertJ Assertion Conflicts
Error:
Root Cause: Static import of
com.palantir.gradle.testing.assertion.GradlePluginTestAssertions.assertThatonly works for specific Gradle testing types, not general Java types.Resolution: Use fully qualified
org.assertj.core.api.Assertions.assertThat()for general assertions on Sets and Strings:Learning: The framework provides specialized assertions for Gradle-specific types (InvocationResult, TaskOutcome), but standard AssertJ must be used for general types.
6. ErrorProne Check: GradleTestPluginsBlock
Error:
Root Cause: The old Nebula test used
apply plugin:in build file strings because it setdefinePluginOutsideOfPluginBlock = true. The ErrorProne check detectsapply plugin:patterns in test code.Resolution: Use the structured
.plugins().add()API instead ofapply plugin:in strings:For complex cases with subprojects in included builds:
Learning: The new framework enforces using the structured plugins API to maintain consistency and enable future automated migrations. This is a deliberate design choice enforced by ErrorProne checks.
7. ErrorProne Check: PreferUncheckedIoException
Error:
Resolution: Change
RuntimeExceptiontoUncheckedIOException:Learning: The framework prefers
UncheckedIOExceptionfor wrapping IOExceptions to allow consumers to better categorize errors.Second Pass - Best Practices Review
After the initial migration compiled successfully, I reviewed the test against the testing-guide.md to ensure best practices were followed:
Multi-Version Testing
✅ Correct: The framework automatically handles multi-version testing via the
@GradlePluginTestsannotation. No explicit parameterization needed (unlike Spock'swhere:clause).File Manipulation
✅ Correct: Used text blocks for multi-line strings as recommended.
✅ Correct: Used
.plugins().add()API instead of manually writing plugin blocks.✅ Correct: Used
.propertiesFile().appendProperty()for properties files.✅ Correct: Used
.file().createEmpty()for creating empty files.MavenRepo Usage
✅ Correct: Used
⚠️ Note: Had to create custom
MavenArtifact.builder()for artifacts with dependencies andMavenArtifact.of()for simple artifacts.makePlatformPom()helper for platform POMs since the framework doesn't have built-in support for this specific case.Configuration Cache Testing
✅ Correct: Tests that use
writeVersionsLocksmanually check configuration cache by running twice with--configuration-cacheflag. This is appropriate for these specific tests.Key Differences Between Nebula and New Framework
extends IntegrationSpec→@GradlePluginTestswhere:with@Unroll→ Automatic via frameworkbuildFile <<→.buildGradle().append()generateMavenRepo()with Nebula →MavenRepoparameter withpublish()addSubproject()→SubProjectparameters with automatic registrationapply plugin:strings →.plugins().add()APIrunTasksWithConfigurationCache()→ Manual--configuration-cacheflagsSummary
The migration was successful after addressing:
The new test is more type-safe, uses modern Java features (text blocks, records), and integrates better with IDEs through proper parameter injection and assertion libraries.
To enable or disable this check, please contact the maintainers of Excavator.