Excavator: Migrate Groovy nebula test GradleJdkToolchainsIntegrationTest to the new Java Junit framework
#641
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 has been generated at test-migration-notes/GradleJdkToolchainsIntegrationTest.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 brief summary of what was accomplished:
Summary
I have successfully migrated the test class
GradleJdkToolchainsIntegrationTestfrom the old Nebula/Groovy testing framework to the new Java-based JUnit 5 testing framework. Here's what was completed:Key Changes Made:
Added delineator comments to the original Groovy test file for easier review comparison
Migrated the test to Java with the following transformations:
@GradlePluginTestsannotation instead of extendingIntegrationSpecGradleInvokerandRootProjectwhere:blocks (multi-version testing is now automatic)standardBuildFileForJdk17Toolchain())Handled special requirements:
./gradlewas a subprocess with customGRADLE_USER_HOMEto verify JDK setuprunGradlewTasksSuccessfully(), etc.) since the framework's TestKit runs in-processworkingDirinside the test project instead of using@TempDir(per Error Prone guidance)Fixed all compilation errors:
GradleJdkTestUtils.path().toFile()instead of.toFile()).exception()to.output()assertionsUncheckedIOExceptioninstead ofRuntimeExceptionFiles.list()streams with try-with-resources.formatted()varwith explicit typesGradleTestPluginsBlockcheck whereapply plugin:is required in buildscript blocksTest compiles successfully with all Error Prone checks passing
Documented all errors in
test-migration-errors.mdfor future referenceThe migrated test maintains all functionality from the original while following the new framework's conventions and best practices.
Claude Code Metrics
Migration Notes
Test Migration Errors and Resolutions
This document tracks errors encountered during the migration of
GradleJdkToolchainsIntegrationTestfrom Groovy/Nebula to Java/JUnit 5, and how they were resolved.First Compilation Pass
Error 1: Package-private constants in GradleJdkTestUtils
Error:
SIMPLIFIED_JDK_11_VERSION has private access in GradleJdkTestUtilsCause: In Groovy,
staticfields without an access modifier are package-private, not public. The Java test couldn't access these constants.Resolution: Copied the constants directly into the test class as private static final fields.
Error 2: No toFile() method on ArbitraryFile
Error:
cannot find symbol: method toFile()Cause:
ArbitraryFileis a record with apath()method, not atoFile()method.Resolution: Changed
.toFile()to.path().toFile()for all file references.Error 3: No exception() method on InvocationResult
Error:
cannot find symbol: method exception()Cause: The new framework's
InvocationResultdoesn't have anexception()method. Build failures are communicated through output text.Resolution: Changed from
Throwables.getRootCause(failingCheck.exception()).getMessage()to checking the output text:failingCheck.output().contains("...")Second Compilation Pass: Error Prone Checks
Error 4: GradleTestTemporaryFile
Error:
Avoid using temporary directories or files in Gradle testsCause: Used
@TempDirforworkingDir, which Error Prone flags as hard to debug.Resolution: Created
workingDirinside the test project using a@BeforeEachmethod:Error 5: GradleTestStringFormatting
Error:
Use the varargs overload of methods to get syntax highlightingCause: Used
.formatted()on text blocks instead of varargs parameters.Resolution: Changed from:
to:
Error 6: PreferUncheckedIoException
Error:
Prefer UncheckedIOException or SafeUncheckedIoException when wrapping IOExceptionCause: Wrapped IOExceptions in generic RuntimeException.
Resolution: Changed
throw new RuntimeException("...", e)tothrow new UncheckedIOException("...", e)for all IOException wrapping.Error 7: StreamResourceLeak
Error:
Streams that encapsulate a closeable resource should be closed using try-with-resourcesCause: Multiple calls to
Files.list()without try-with-resources.Resolution: Created a helper method that properly closes streams:
For one case that needed
allMatch(), used try-with-resources inline.Error 8: VarUsage
Error:
The 'var' keyword results in illegible code in most cases and should not be usedCause: Used
varfor SubProject declarations.Resolution: Changed
var subprojectLib21 = ...to explicit typecom.palantir.gradle.testing.project.SubProject subprojectLib21 = ...Error 9: GradleTestPluginsBlock
Error:
Plugins must be added using .plugins().add() methodCause: Used
apply plugin:syntax in buildscript blocks withinprepend()calls.Resolution: Since these are in buildscript blocks with manual classpath injection (not regular plugin blocks), suppressed the check:
Framework Differences Discovered
Custom Gradlew Execution
This test is unique in that it needs to run
./gradlewas a separate process with a customGRADLE_USER_HOMEto verify JDK setup works correctly. The new testing framework uses Gradle TestKit which runs in-process. To handle this:runGradlewTasksSuccessfully(),runGradlewTasksWithFailure(),runGradlewTasks(), andgetProcessBuilder()ProcessBuilderworkingDiris set as theGRADLE_USER_HOMEenvironment variableMulti-version Testing
The old Groovy test used Spock's data tables with
where: gradleVersionNumber << GRADLE_TEST_VERSIONS. The new framework handles multi-version testing automatically through the@GradlePluginTestsannotation, so individual test methods don't need parameters.Second Review Pass
After reviewing the testing-guide.md and the migrated test:
Delineator comments preserved: All
// ***DELINEATOR FOR REVIEW:comments were preserved from the Groovy test to assist human reviewers.Helper methods for build file setup: Created
standardBuildFileForJdk17Toolchain()method to replace the pattern from the Groovy test, returningGradleFilefor fluent chaining.Proper exception handling: All IOException wrapping uses
UncheckedIOExceptionas required by Error Prone.Resource management: All streams from
Files.list()are properly closed.Explicit types: No use of
varkeyword to maintain code readability.Summary
The migration was successful after addressing compilation errors related to:
toFile(), noexception())The migrated test maintains all the functionality of the original while following the new framework's conventions and Error Prone checks.
To enable or disable this check, please contact the maintainers of Excavator.