-
Notifications
You must be signed in to change notification settings - Fork 135
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ensure spock 2/nebula-test 10 tests actually run #1929
Changes from all commits
d896e9e
0651596
bc68e18
1f9cc26
118cb97
e99dce0
1e4ac7c
4393e31
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
type: fix | ||
fix: | ||
description: Ensure nebula-test 10/Spock 2 test run by automatically setting `useJUnitPlatform()` | ||
on test tasks. Add extra verification to the `checkJUnitDependencies` task for | ||
nebula-test 10/Spock 2 tests. | ||
links: | ||
- https://github.com/palantir/gradle-baseline/pull/1929 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,18 +16,20 @@ | |
|
||
package com.palantir.baseline.plugins; | ||
|
||
import com.google.common.base.Predicate; | ||
import com.google.common.collect.ImmutableSet; | ||
import com.palantir.baseline.tasks.CheckJUnitDependencies; | ||
import com.palantir.baseline.tasks.CheckUnusedDependenciesTask; | ||
import com.palantir.baseline.util.VersionUtils; | ||
import java.util.Objects; | ||
import java.util.Optional; | ||
import org.gradle.api.Plugin; | ||
import org.gradle.api.Project; | ||
import org.gradle.api.Task; | ||
import org.gradle.api.artifacts.Dependency; | ||
import org.gradle.api.artifacts.component.ModuleComponentIdentifier; | ||
import org.gradle.api.artifacts.result.ResolvedComponentResult; | ||
import org.gradle.api.plugins.JavaPlugin; | ||
import org.gradle.api.plugins.JavaPluginConvention; | ||
import org.gradle.api.specs.Spec; | ||
import org.gradle.api.tasks.SourceSet; | ||
import org.gradle.api.tasks.TaskContainer; | ||
import org.gradle.api.tasks.TaskProvider; | ||
|
@@ -61,38 +63,44 @@ public void apply(Project project) { | |
}); | ||
|
||
project.getPlugins().withType(JavaPlugin.class, unusedPlugin -> { | ||
// afterEvaluate necessary because the junit-jupiter dep might be added further down the build.gradle | ||
project.afterEvaluate(proj -> { | ||
proj.getConvention() | ||
.getPlugin(JavaPluginConvention.class) | ||
.getSourceSets() | ||
.matching(ss -> hasCompileDependenciesMatching(proj, ss, BaselineTesting::isJunitJupiter)) | ||
.forEach(ss -> { | ||
Optional<Test> maybeTestTask = getTestTaskForSourceSet(proj, ss); | ||
if (!maybeTestTask.isPresent()) { | ||
log.warn("Detected 'org:junit.jupiter:junit-jupiter', but unable to find test task"); | ||
return; | ||
} | ||
log.info( | ||
"Detected 'org:junit.jupiter:junit-jupiter', enabling useJUnitPlatform() on {}", | ||
maybeTestTask.get().getName()); | ||
enableJunit5ForTestTask(maybeTestTask.get()); | ||
|
||
// Also wire up a test ignore for this source set | ||
project.getPlugins().withType(BaselineExactDependencies.class, exactDeps -> { | ||
TaskContainer tasks = project.getTasks(); | ||
tasks.named( | ||
BaselineExactDependencies.checkUnusedDependenciesNameForSourceSet(ss), | ||
CheckUnusedDependenciesTask.class, | ||
task -> task.ignore("org.junit.jupiter", "junit-jupiter")); | ||
}); | ||
TaskProvider<CheckJUnitDependencies> checkJUnitDependencies = | ||
project.getTasks().register("checkJUnitDependencies", CheckJUnitDependencies.class); | ||
|
||
project.getConvention() | ||
.getPlugin(JavaPluginConvention.class) | ||
.getSourceSets() | ||
.configureEach(sourceSet -> { | ||
getTestTaskForSourceSet(project, sourceSet).ifPresent(testTask -> { | ||
testTask.dependsOn(checkJUnitDependencies); | ||
}); | ||
}); | ||
|
||
TaskProvider<CheckJUnitDependencies> task = | ||
project.getTasks().register("checkJUnitDependencies", CheckJUnitDependencies.class); | ||
ifHasResolvedCompileDependenciesMatching( | ||
project, | ||
sourceSet, | ||
BaselineTesting::requiresJunitPlatform, | ||
() -> fixSourceSet(project, sourceSet)); | ||
}); | ||
}); | ||
} | ||
|
||
project.getTasks().findByName(JavaPlugin.TEST_TASK_NAME).dependsOn(task); | ||
private void fixSourceSet(Project project, SourceSet ss) { | ||
Optional<Test> maybeTestTask = getTestTaskForSourceSet(project, ss); | ||
if (!maybeTestTask.isPresent()) { | ||
log.warn("Detected 'org:junit.jupiter:junit-jupiter', but unable to find test task"); | ||
return; | ||
} | ||
log.info( | ||
"Detected 'org:junit.jupiter:junit-jupiter', enabling useJUnitPlatform() on {}", | ||
maybeTestTask.get().getName()); | ||
enableJunit5ForTestTask(maybeTestTask.get()); | ||
|
||
// Also wire up a test ignore for this source set | ||
project.getPlugins().withType(BaselineExactDependencies.class, exactDeps -> { | ||
TaskContainer tasks = project.getTasks(); | ||
tasks.named( | ||
BaselineExactDependencies.checkUnusedDependenciesNameForSourceSet(ss), | ||
CheckUnusedDependenciesTask.class, | ||
task -> task.ignore("org.junit.jupiter", "junit-jupiter")); | ||
}); | ||
} | ||
|
||
|
@@ -112,20 +120,32 @@ public static Optional<Test> getTestTaskForSourceSet(Project proj, SourceSet ss) | |
return Optional.empty(); | ||
} | ||
|
||
private static boolean hasCompileDependenciesMatching(Project project, SourceSet sourceSet, Spec<Dependency> spec) { | ||
return project | ||
.getConfigurations() | ||
.getByName(sourceSet.getCompileClasspathConfigurationName()) | ||
.getAllDependencies() | ||
.matching(spec) | ||
.stream() | ||
.findAny() | ||
.isPresent(); | ||
private static void ifHasResolvedCompileDependenciesMatching( | ||
Project project, SourceSet sourceSet, Predicate<ModuleComponentIdentifier> spec, Runnable runnable) { | ||
project.getConfigurations() | ||
.getByName(sourceSet.getRuntimeClasspathConfigurationName()) | ||
.getIncoming() | ||
.afterResolve(deps -> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since we need to distinguish between Spock 1 and Spock 2, we need to actually resolve the configuration to get a version number. It's actually quite tricky to resolve here, as it fails foul of the checks we have to prevent resolving configuration at configuration time, which destroys perf. Instead, we wait for this configuration to resolved, which will happen before the test is run, by the (This would be so much easier if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was initially thinking that it might be sufficient to just go through the explicitly declared deps which would not require resolution. However most of the time Spock is brought in as a transitive and so you have to do resolution :( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I initially did that and checked for nebula-test too, but until resolution happens you don't know the version number, so can't decide whether or not to do the right thing |
||
boolean anyMatch = deps.getResolutionResult().getAllComponents().stream() | ||
.map(ResolvedComponentResult::getId) | ||
.filter(componentId -> componentId instanceof ModuleComponentIdentifier) | ||
.map(componentId -> (ModuleComponentIdentifier) componentId) | ||
.anyMatch(spec); | ||
|
||
if (anyMatch) { | ||
runnable.run(); | ||
} | ||
}); | ||
} | ||
|
||
private static boolean requiresJunitPlatform(ModuleComponentIdentifier dep) { | ||
return isDep(dep, "org.junit.jupiter", "junit-jupiter") | ||
|| (isDep(dep, "org.spockframework", "spock-core") | ||
&& VersionUtils.majorVersionNumber(dep.getVersion()) >= 2); | ||
} | ||
|
||
private static boolean isJunitJupiter(Dependency dep) { | ||
return Objects.equals(dep.getGroup(), "org.junit.jupiter") | ||
&& dep.getName().equals("junit-jupiter"); | ||
private static boolean isDep(ModuleComponentIdentifier dep, String group, String name) { | ||
return group.equals(dep.getGroup()) && name.equals(dep.getModule()); | ||
} | ||
|
||
private static void enableJunit5ForTestTask(Test task) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/* | ||
* (c) Copyright 2021 Palantir Technologies Inc. All rights reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package com.palantir.baseline.util; | ||
|
||
import com.google.common.base.Splitter; | ||
import org.gradle.api.GradleException; | ||
|
||
public final class VersionUtils { | ||
public static int majorVersionNumber(String version) { | ||
return Integer.parseInt(Splitter.on('.') | ||
.splitToStream(version) | ||
.findFirst() | ||
.orElseThrow(() -> new GradleException("Cannot find major version number for version " + version))); | ||
} | ||
|
||
private VersionUtils() {} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should use the
JavaPluginExtension
as conventions are deprecated and to be removed with Gradle 8.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried, but Gradle 6 doesn't have the
getSourceSets
method we need 118cb97There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I remember encountering this before. I guess Gradle 7 is the bridge version then at with Gradle 8 we have to cut support for Gradle 6. Fine for now then!