From 14101fcac3e210bace49a5c56af585e84ae5dfef Mon Sep 17 00:00:00 2001 From: chrisnikoli Date: Wed, 28 Aug 2024 14:02:01 -0700 Subject: [PATCH] Add JUnit attachment support --- .../allure/junitxml/JunitXmlPlugin.java | 24 ++++++++++++-- .../allure/junitxml/JunitXmlPluginTest.java | 33 ++++++++++++++++++- .../junitdata/TEST-test.Attachment.xml | 10 ++++++ 3 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 plugins/junit-xml-plugin/src/test/resources/junitdata/TEST-test.Attachment.xml diff --git a/plugins/junit-xml-plugin/src/main/java/io/qameta/allure/junitxml/JunitXmlPlugin.java b/plugins/junit-xml-plugin/src/main/java/io/qameta/allure/junitxml/JunitXmlPlugin.java index 1bea7b2e1..be8f7979b 100644 --- a/plugins/junit-xml-plugin/src/main/java/io/qameta/allure/junitxml/JunitXmlPlugin.java +++ b/plugins/junit-xml-plugin/src/main/java/io/qameta/allure/junitxml/JunitXmlPlugin.java @@ -23,6 +23,7 @@ import io.qameta.allure.datetime.DateTimeParser; import io.qameta.allure.datetime.LocalDateTimeParser; import io.qameta.allure.datetime.ZonedDateTimeParser; +import io.qameta.allure.entity.Attachment; import io.qameta.allure.entity.LabelName; import io.qameta.allure.entity.Parameter; import io.qameta.allure.entity.StageResult; @@ -44,6 +45,7 @@ import java.nio.file.Files; import java.nio.file.InvalidPathException; import java.nio.file.Path; +import java.nio.file.Paths; import java.time.ZoneId; import java.time.ZoneOffset; import java.util.ArrayList; @@ -54,12 +56,13 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; import static io.qameta.allure.entity.LabelName.RESULT_FORMAT; import static java.nio.file.Files.newDirectoryStream; -import static java.util.Collections.singletonList; import static java.util.Objects.isNull; import static java.util.Objects.nonNull; @@ -100,6 +103,8 @@ public class JunitXmlPlugin implements Reader { private static final String XML_GLOB = "*.xml"; + private static final Pattern SYSTEM_OUTPUT_ATTACHMENT = Pattern.compile(" *\\[\\[ATTACHMENT\\|(?.*)\\]\\]"); + private static final Map RETRIES; static { @@ -185,19 +190,34 @@ private void parseTestCase(final TestSuiteInfo info, final XmlElement testCaseEl result.setFlaky(isFlaky(testCaseElement)); setStatusDetails(result, testCaseElement); final StageResult stageResult = new StageResult(); + final List attachments = new ArrayList<>(); getLogMessage(testCaseElement).ifPresent(logMessage -> { final List lines = splitLines(logMessage); final List steps = lines .stream() + .filter(line -> !SYSTEM_OUTPUT_ATTACHMENT.matcher(line).matches()) .map(line -> new Step().setName(line)) .collect(Collectors.toList()); stageResult.setSteps(steps); + lines + .stream() + .filter(line -> SYSTEM_OUTPUT_ATTACHMENT.matcher(line).matches()) + .forEach(line -> { + final Matcher m = SYSTEM_OUTPUT_ATTACHMENT.matcher(line); + if (m.find()) { + final Path attachmentPath = Paths.get(m.group("path")).toAbsolutePath(); + final Attachment attachment = visitor.visitAttachmentFile(attachmentPath); + attachment.setName(attachmentPath.getFileName().toString()); + attachments.add(attachment); + } + }); }); getLogFile(resultsDirectory, className) .filter(Files::exists) .map(visitor::visitAttachmentFile) .map(attachment1 -> attachment1.setName("System out")) - .ifPresent(attachment -> stageResult.setAttachments(singletonList(attachment))); + .ifPresent(attachments::add); + stageResult.setAttachments(attachments); result.setTestStage(stageResult); visitor.visitTestResult(result); diff --git a/plugins/junit-xml-plugin/src/test/java/io/qameta/allure/junitxml/JunitXmlPluginTest.java b/plugins/junit-xml-plugin/src/test/java/io/qameta/allure/junitxml/JunitXmlPluginTest.java index c4ea82637..a14b7d78a 100644 --- a/plugins/junit-xml-plugin/src/test/java/io/qameta/allure/junitxml/JunitXmlPluginTest.java +++ b/plugins/junit-xml-plugin/src/test/java/io/qameta/allure/junitxml/JunitXmlPluginTest.java @@ -127,11 +127,42 @@ void shouldAddLogAsAttachment() throws Exception { assertThat(testStage.getAttachments()) .describedAs("Should add an attachment") .hasSize(1) - .describedAs("Attachment should has right uid and name") + .describedAs("Attachment should have right uid and name") .extracting(Attachment::getName, Attachment::getUid) .containsExactly(Tuple.tuple("System out", "some-uid")); } + @Test + void shouldAddSystemOutAsAttachment() throws Exception { + final Attachment hey = new Attachment().setUid("some-uid"); + when(visitor.visitAttachmentFile(any())).thenReturn(hey); + process( + "junitdata/TEST-test.Attachment.xml", "TEST-test.Attachment.xml" + ); + + final ArgumentCaptor attachmentCaptor = ArgumentCaptor.captor(); + verify(visitor, times(1)).visitAttachmentFile(attachmentCaptor.capture()); + + assertThat(attachmentCaptor.getValue()) + .isRegularFile() + .hasContent("some-test-log"); + + final ArgumentCaptor captor = ArgumentCaptor.captor(); + verify(visitor, times(1)).visitTestResult(captor.capture()); + + final StageResult testStage = captor.getValue().getTestStage(); + assertThat(testStage) + .describedAs("Should create a test stage") + .isNotNull(); + + assertThat(testStage.getAttachments()) + .describedAs("Should add an attachment") + .hasSize(1) + .describedAs("Attachment should have right uid and name") + .extracting(Attachment::getName, Attachment::getUid) + .containsExactly(Tuple.tuple("test.SampleTest.txt", "some-uid")); + } + @Test void shouldAddLabels() throws Exception { process( diff --git a/plugins/junit-xml-plugin/src/test/resources/junitdata/TEST-test.Attachment.xml b/plugins/junit-xml-plugin/src/test/resources/junitdata/TEST-test.Attachment.xml new file mode 100644 index 000000000..3cbb8b13e --- /dev/null +++ b/plugins/junit-xml-plugin/src/test/resources/junitdata/TEST-test.Attachment.xml @@ -0,0 +1,10 @@ + + + + Step 1 +Step 2 +Step 3 +[[ATTACHMENT|src/test/resources/junitdata/test.SampleTest.txt]] + + +