From c71b796af7c369493f49c53bc473a0dd333c0a36 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 28 May 2025 12:56:00 +0200 Subject: [PATCH] Allow publishing files to an existing directory Prior to this commit, both `TestReporter` and `ExtensionContext` threw an exception when `publishDirectory` was called with an existing directory. Now, they only attempt to create the directory if it doesn't already exist. --- .../release-notes/release-notes-5.13.0.adoc | 2 ++ .../jupiter/api/extension/ExtensionContext.java | 2 +- .../engine/descriptor/AbstractExtensionContext.java | 4 +++- .../engine/descriptor/ExtensionContextTests.java | 13 +++++++++++++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.0.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.0.adoc index 35efebf70ac0..11135967b332 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.0.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.0.adoc @@ -188,6 +188,8 @@ to start reporting discovery issues. failures. * Add support for Kotlin `Sequence` to `@MethodSource`, `@FieldSource`, and `@TestFactory`. +* Allow publishing files to an existing directory via `TestReporter` and + `ExtensionContext`, for example, when re-running a test class. [[release-notes-5.13.0-junit-vintage]] diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContext.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContext.java index a4f2a09a56b2..fd09f1d47de3 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContext.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContext.java @@ -419,7 +419,7 @@ default void publishReportEntry(String value) { * and attach it to the current test or container. * *

The directory will be resolved and created in the report output directory - * prior to invoking the supplied action. + * prior to invoking the supplied action, if it doesn't already exist. * * @param name the name of the directory to be attached; never {@code null} * or blank and must not contain any path separators diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java index a7aa5fe248c0..b3497dfc0c80 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java @@ -161,7 +161,9 @@ public void publishDirectory(String name, ThrowingConsumer action) { Preconditions.notNull(action, "action must not be null"); ThrowingConsumer enhancedAction = path -> { - Files.createDirectory(path); + if (!Files.isDirectory(path)) { + Files.createDirectory(path); + } action.accept(path); }; publishFileEntry(name, enhancedAction, file -> { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ExtensionContextTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ExtensionContextTests.java index f48979ec7dff..2599244c739c 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ExtensionContextTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ExtensionContextTests.java @@ -382,6 +382,19 @@ void failsWhenAttemptingToPublishRegularFilesAsDirectories(@TempDir Path tempDir "Published path must be a directory: " + tempDir.resolve("OuterClass").resolve("test")); } + @Test + void allowsPublishingToTheSameDirectoryTwice(@TempDir Path tempDir) { + var extensionContext = createExtensionContextForFilePublishing(tempDir); + + extensionContext.publishDirectory("test", + dir -> Files.writeString(dir.resolve("nested1.txt"), "Nested content 1")); + extensionContext.publishDirectory("test", + dir -> Files.writeString(dir.resolve("nested2.txt"), "Nested content 2")); + + assertThat(tempDir.resolve("OuterClass/test/nested1.txt")).hasContent("Nested content 1"); + assertThat(tempDir.resolve("OuterClass/test/nested2.txt")).hasContent("Nested content 2"); + } + private ExtensionContext createExtensionContextForFilePublishing(Path tempDir) { return createExtensionContextForFilePublishing(tempDir, mock(EngineExecutionListener.class), outerClassDescriptor(null));