From 36f70ab5cfe9869d750ab3af3ab3466822cd0e62 Mon Sep 17 00:00:00 2001 From: Scott Dugas Date: Mon, 17 Mar 2025 16:50:31 -0400 Subject: [PATCH] Allow having YamlTestExtension include method name in test names When publishing to JUnit xml style files there is no hierarchy, so some tools will just show the class name and description, making it hard to tell what tests were run, or failed. If YamlTestExtension is used in an environment where that is the case this can be used to have the output include the method name. For example: - showcasingTests(Embedded) - showcasingTests(MultiServer (Embedded then !current_version)) ... Instead of - YamlIntegrationTests - showcasingTests(Runner) - Embedded - MultiServer (Embedded then !current_version) I thought about making this configurable via system property, but I think having it configured by a constructor parameter aligns more with PRs #3252 and #3251 --- .../yamltests/YamlTestExtension.java | 44 ++++++++++++++----- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/yaml-tests/src/main/java/com/apple/foundationdb/relational/yamltests/YamlTestExtension.java b/yaml-tests/src/main/java/com/apple/foundationdb/relational/yamltests/YamlTestExtension.java index 58f1307585..1f5d8a6953 100644 --- a/yaml-tests/src/main/java/com/apple/foundationdb/relational/yamltests/YamlTestExtension.java +++ b/yaml-tests/src/main/java/com/apple/foundationdb/relational/yamltests/YamlTestExtension.java @@ -66,13 +66,23 @@ public class YamlTestExtension implements TestTemplateInvocationContextProvider, private List servers; @Nullable private final String clusterFile; + private final boolean includeMethodInDescriptions; public YamlTestExtension() { - this.clusterFile = null; // it will get it from the environment + this(null, false); } - public YamlTestExtension(@Nullable final String clusterFile) { + /** + * Create a new extension with some configuration. + * @param clusterFile a custom cluster file to use, or {@code null} to inherit it from the environment, namely + * {@code FDB_CLUSTER_FILE}. + * @param includeMethodInDescriptions Set this to {@code true} if publishing test results to something that cannot + * handle complex test hierarchies. In the record layer we maintain the full hierarchy in the output, so this is not + * necessary, but if integrating some other tools this might be necessary. + */ + public YamlTestExtension(@Nullable final String clusterFile, final boolean includeMethodInDescriptions) { this.clusterFile = clusterFile; + this.includeMethodInDescriptions = includeMethodInDescriptions; } @Override @@ -184,11 +194,11 @@ public boolean supportsTestTemplate(final ExtensionContext context) { @Override public Stream provideTestTemplateInvocationContexts(final ExtensionContext context) { final var testClass = context.getRequiredTestClass(); + final var testMethod = context.getRequiredTestMethod(); if (testClass.getAnnotation(MaintainYamlTestConfig.class) != null) { final var annotation = testClass.getAnnotation(MaintainYamlTestConfig.class); - return provideInvocationContextsForMaintenance(annotation); + return provideInvocationContextsForMaintenance(annotation, testMethod.getName()); } - final var testMethod = context.getRequiredTestMethod(); if (testMethod.getAnnotation(ExcludeYamlTestConfig.class) != null) { // excluded tests are still included as configs so that they show up in the test run as skipped, rather than // just not being there. This may waste some resources if all the tests being run exclude a config that has @@ -196,22 +206,24 @@ public Stream provideTestTemplateInvocationContex final var annotation = testMethod.getAnnotation(ExcludeYamlTestConfig.class); return testConfigs .stream() - .map(config -> new Context(config, annotation.reason(), annotation.value())); + .map(config -> new Context(config, annotation.reason(), annotation.value(), + includeMethodInDescriptions, testMethod.getName())); } else if (testMethod.getAnnotation(MaintainYamlTestConfig.class) != null) { final var annotation = testMethod.getAnnotation(MaintainYamlTestConfig.class); - return provideInvocationContextsForMaintenance(annotation); + return provideInvocationContextsForMaintenance(annotation, testMethod.getName()); } return testConfigs .stream() - .map(config -> new Context(config, "", null)); + .map(config -> new Context(config, "", null, includeMethodInDescriptions, testMethod.getName())); } - private Stream provideInvocationContextsForMaintenance(@Nonnull final MaintainYamlTestConfig annotation) { + private Stream provideInvocationContextsForMaintenance( + @Nonnull final MaintainYamlTestConfig annotation, @Nonnull final String methodName) { return maintainConfigs .stream() .map(config -> new Context(config, "maintenance not needed", - Objects.requireNonNull(annotation.value()))); + Objects.requireNonNull(annotation.value()), includeMethodInDescriptions, methodName)); } /** @@ -225,17 +237,27 @@ private static class Context implements TestTemplateInvocationContext { private final String excludedReason; @Nullable private final YamlTestConfigFilters configFilters; + private final boolean includeMethodInDescriptions; + @Nonnull + private final String methodName; public Context(@Nonnull final YamlTestConfig config, @Nonnull final String excludedReason, - @Nullable final YamlTestConfigFilters configFilters) { + @Nullable final YamlTestConfigFilters configFilters, + final boolean includeMethodInDescriptions, @Nonnull final String methodName) { this.config = config; this.excludedReason = excludedReason; this.configFilters = configFilters; + this.includeMethodInDescriptions = includeMethodInDescriptions; + this.methodName = methodName; } @Override public String getDisplayName(int invocationIndex) { - return config.toString(); + if (includeMethodInDescriptions) { + return methodName + "(" + config + ")"; + } else { + return config.toString(); + } } @Override