Test reporter fixes (#1597)

* Fix error message when an invalid test reporter is supplied in Gradle
* Fix Gradle property name in docs
* Fix Gradle property name in tasks
* Introduce `TestReporter.default`, and use it in places where default
is applied
* Remove calls to `convention()`; this is not required because the input
is optional anyways.
This commit is contained in:
Daniel Chao
2026-05-19 11:32:51 -07:00
committed by GitHub
parent 3fbcd463e0
commit e34c3e8c4f
10 changed files with 80 additions and 39 deletions
+2 -2
View File
@@ -323,7 +323,7 @@ Whether to ignore expected example files and generate them again.
==== ====
[[test-reporter]] [[test-reporter]]
.test-reporter: Property<String> .testReporter: Property<String>
[%collapsible] [%collapsible]
==== ====
Default: `"spec"` + Default: `"spec"` +
@@ -686,7 +686,7 @@ Default: `false` +
Whether to ignore expected example files and generate them again. Whether to ignore expected example files and generate them again.
==== ====
.test-reporter: Property<String> .testReporter: Property<String>
[%collapsible] [%collapsible]
==== ====
Default: `"spec"` + Default: `"spec"` +
@@ -22,5 +22,5 @@ class CliTestOptions(
val overwrite: Boolean = false, val overwrite: Boolean = false,
val junitAggregateReports: Boolean = false, val junitAggregateReports: Boolean = false,
val junitAggregateSuiteName: String = "pkl-tests", val junitAggregateSuiteName: String = "pkl-tests",
val reporter: TestReporter = TestReporter.SPEC, val reporter: TestReporter = TestReporter.default,
) )
@@ -17,5 +17,9 @@ package org.pkl.commons.cli
enum class TestReporter { enum class TestReporter {
SPEC, SPEC,
MINIMAL, MINIMAL;
companion object {
@JvmStatic val default: TestReporter = SPEC
}
} }
@@ -57,7 +57,7 @@ class TestOptions : OptionGroup() {
option(names = arrayOf("--test-reporter"), help = "Which test reporter to use for CLI output.") option(names = arrayOf("--test-reporter"), help = "Which test reporter to use for CLI output.")
.enum<TestReporter> { it.name.lowercase() } .enum<TestReporter> { it.name.lowercase() }
.single() .single()
.default(TestReporter.SPEC) .default(TestReporter.default)
val cliTestOptions: CliTestOptions by lazy { val cliTestOptions: CliTestOptions by lazy {
CliTestOptions( CliTestOptions(
@@ -100,7 +100,6 @@ public class PklPlugin implements Plugin<Project> {
spec.getOutputPath() spec.getOutputPath()
.convention(project.getLayout().getBuildDirectory().dir("generated/pkl/packages")); .convention(project.getLayout().getBuildDirectory().dir("generated/pkl/packages"));
spec.getOverwrite().convention(false); spec.getOverwrite().convention(false);
spec.getReporter().convention("spec");
var packageTask = createTask(project, ProjectPackageTask.class, spec); var packageTask = createTask(project, ProjectPackageTask.class, spec);
packageTask.configure( packageTask.configure(
task -> { task -> {
@@ -109,7 +108,7 @@ public class PklPlugin implements Plugin<Project> {
task.getSkipPublishCheck().set(spec.getSkipPublishCheck()); task.getSkipPublishCheck().set(spec.getSkipPublishCheck());
task.getJunitReportsDir().set(spec.getJunitReportsDir()); task.getJunitReportsDir().set(spec.getJunitReportsDir());
task.getOverwrite().set(spec.getOverwrite()); task.getOverwrite().set(spec.getOverwrite());
task.getTestReporter().set(spec.getReporter()); task.getTestReporter().set(spec.getTestReporter());
}); });
project project
.getPluginManager() .getPluginManager()
@@ -280,7 +279,6 @@ public class PklPlugin implements Plugin<Project> {
configureBaseSpec(project, spec); configureBaseSpec(project, spec);
spec.getOverwrite().convention(false); spec.getOverwrite().convention(false);
spec.getTestReporter().convention("spec");
var testTask = createModulesTask(project, TestTask.class, spec); var testTask = createModulesTask(project, TestTask.class, spec);
testTask.configure( testTask.configure(
@@ -30,5 +30,5 @@ public interface ProjectPackageSpec extends BasePklSpec {
Property<Boolean> getSkipPublishCheck(); Property<Boolean> getSkipPublishCheck();
Property<String> getReporter(); Property<String> getTestReporter();
} }
@@ -16,6 +16,7 @@
package org.pkl.gradle.task; package org.pkl.gradle.task;
import static org.pkl.gradle.utils.PluginUtils.mapAndGetOrNull; import static org.pkl.gradle.utils.PluginUtils.mapAndGetOrNull;
import static org.pkl.gradle.utils.PluginUtils.toTestReporter;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.nio.file.Path; import java.nio.file.Path;
@@ -34,7 +35,6 @@ import org.gradle.api.tasks.PathSensitivity;
import org.gradle.api.tasks.UntrackedTask; import org.gradle.api.tasks.UntrackedTask;
import org.pkl.cli.CliProjectPackager; import org.pkl.cli.CliProjectPackager;
import org.pkl.commons.cli.CliTestOptions; import org.pkl.commons.cli.CliTestOptions;
import org.pkl.commons.cli.TestReporter;
@UntrackedTask(because = "Output names are known only after execution") @UntrackedTask(because = "Output names are known only after execution")
public abstract class ProjectPackageTask extends BasePklTask { public abstract class ProjectPackageTask extends BasePklTask {
@@ -80,18 +80,6 @@ public abstract class ProjectPackageTask extends BasePklTask {
if (projectDirectories.isEmpty()) { if (projectDirectories.isEmpty()) {
throw new InvalidUserDataException("No project directories specified."); throw new InvalidUserDataException("No project directories specified.");
} }
TestReporter testReporter;
try {
testReporter = TestReporter.valueOf(getTestReporter().getOrElse("SPEC").toUpperCase());
} catch (IllegalArgumentException e) {
throw new InvalidUserDataException(
"Invalid reporter: '%s'. Valid reporter options: %s"
.formatted(
getTestReporter().get(),
TestReporter.getEntries().stream()
.map(it -> it.name().toLowerCase())
.collect(Collectors.joining(", "))));
}
new CliProjectPackager( new CliProjectPackager(
getCliBaseOptions(), getCliBaseOptions(),
@@ -101,7 +89,7 @@ public abstract class ProjectPackageTask extends BasePklTask {
getOverwrite().get(), getOverwrite().get(),
getJunitAggregateReports().getOrElse(false), getJunitAggregateReports().getOrElse(false),
getJunitAggregateSuiteName().get(), getJunitAggregateSuiteName().get(),
testReporter), toTestReporter(getTestReporter())),
getOutputPath().get().getAsFile().getAbsolutePath(), getOutputPath().get().getAsFile().getAbsolutePath(),
getSkipPublishCheck().getOrElse(false), getSkipPublishCheck().getOrElse(false),
new PrintWriter(System.out), new PrintWriter(System.out),
@@ -16,10 +16,9 @@
package org.pkl.gradle.task; package org.pkl.gradle.task;
import static org.pkl.gradle.utils.PluginUtils.mapAndGetOrNull; import static org.pkl.gradle.utils.PluginUtils.mapAndGetOrNull;
import static org.pkl.gradle.utils.PluginUtils.toTestReporter;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.stream.Collectors;
import org.gradle.api.InvalidUserDataException;
import org.gradle.api.file.DirectoryProperty; import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.provider.Property; import org.gradle.api.provider.Property;
import org.gradle.api.tasks.CacheableTask; import org.gradle.api.tasks.CacheableTask;
@@ -28,7 +27,6 @@ import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.OutputDirectory; import org.gradle.api.tasks.OutputDirectory;
import org.pkl.cli.CliTestRunner; import org.pkl.cli.CliTestRunner;
import org.pkl.commons.cli.CliTestOptions; import org.pkl.commons.cli.CliTestOptions;
import org.pkl.commons.cli.TestReporter;
@CacheableTask @CacheableTask
public abstract class TestTask extends ModulesTask { public abstract class TestTask extends ModulesTask {
@@ -57,18 +55,6 @@ public abstract class TestTask extends ModulesTask {
@Override @Override
protected void doRunTask() { protected void doRunTask() {
TestReporter testReporter;
try {
testReporter = TestReporter.valueOf(getTestReporter().getOrElse("SPEC").toUpperCase());
} catch (IllegalArgumentException e) {
throw new InvalidUserDataException(
"Invalid reporter: '%s'. Valid reporter options: %s"
.formatted(
getTestReporter().get(),
TestReporter.getEntries().stream()
.map(it -> it.name().toLowerCase())
.collect(Collectors.joining(", "))));
}
new CliTestRunner( new CliTestRunner(
getCliBaseOptions(), getCliBaseOptions(),
new CliTestOptions( new CliTestOptions(
@@ -76,7 +62,7 @@ public abstract class TestTask extends ModulesTask {
getOverwrite().get(), getOverwrite().get(),
getJunitAggregateReports().getOrElse(false), getJunitAggregateReports().getOrElse(false),
getJunitAggregateSuiteName().get(), getJunitAggregateSuiteName().get(),
testReporter), toTestReporter(getTestReporter())),
new PrintWriter(System.out), new PrintWriter(System.out),
new PrintWriter(System.err)) new PrintWriter(System.err))
.run(); .run();
@@ -31,6 +31,7 @@ import org.gradle.api.file.FileSystemLocation;
import org.gradle.api.file.RegularFile; import org.gradle.api.file.RegularFile;
import org.gradle.api.provider.Provider; import org.gradle.api.provider.Provider;
import org.jspecify.annotations.Nullable; import org.jspecify.annotations.Nullable;
import org.pkl.commons.cli.TestReporter;
import org.pkl.core.ImportGraph; import org.pkl.core.ImportGraph;
import org.pkl.core.util.IoUtils; import org.pkl.core.util.IoUtils;
@@ -175,4 +176,31 @@ public final class PluginUtils {
@Nullable T value = provider.getOrNull(); @Nullable T value = provider.getOrNull();
return value == null ? null : f.apply(value); return value == null ? null : f.apply(value);
} }
public static TestReporter toTestReporter(Provider<String> input) {
var inputStr = input.getOrNull();
if (inputStr == null) {
return TestReporter.getDefault();
}
try {
return TestReporter.valueOf(inputStr.toUpperCase());
} catch (IllegalArgumentException e) {
var sb = new StringBuilder("Invalid test reporter: '");
sb.append(inputStr).append("'. ");
sb.append("Valid reporters: ");
var isFirst = true;
// `enumEntries()` is not available in Kotlin versions below 1.8
//noinspection EnumValuesSoftDeprecateInJava
for (var value : TestReporter.values()) {
if (isFirst) {
isFirst = false;
} else {
sb.append(", ");
}
sb.append('\'').append(value.toString().toLowerCase()).append('\'');
}
sb.append(".");
throw new InvalidUserDataException(sb.toString());
}
}
} }
@@ -332,6 +332,43 @@ class TestsTest : AbstractTest() {
) )
} }
@Test
fun `minimal test reporter`() {
writeFile(
"test.pkl",
"""
amends "pkl:test"
facts {
["passes"] {
true
}
["fails"] {
false
}
}
"""
.trimIndent(),
)
writeFile("test.pkl-expected.pcf", bigTestExpected)
writeBuildFile("testReporter = 'minimal'")
runTask("evalTest", expectFailure = true)
}
@Test
fun `invalid test reporter`() {
writePklFile()
writeFile("test.pkl-expected.pcf", bigTestExpected)
writeBuildFile("testReporter = 'not a reporter'")
val output = runTask("evalTest", expectFailure = true)
assertThat(output.output)
.contains("Invalid test reporter: 'not a reporter'. Valid reporters: 'spec', 'minimal'.")
}
private val examples = private val examples =
""" """
["user 0"] { ["user 0"] {