diff --git a/allure-generator/package-lock.json b/allure-generator/package-lock.json index a656fef6d..93925ae8b 100644 --- a/allure-generator/package-lock.json +++ b/allure-generator/package-lock.json @@ -4917,8 +4917,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -4939,14 +4938,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4959,20 +4956,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -5087,8 +5081,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -5100,7 +5093,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -5115,7 +5107,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -5226,8 +5217,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -5239,7 +5229,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -5360,7 +5349,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -5380,7 +5368,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -5409,8 +5396,7 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.2", @@ -8086,7 +8072,6 @@ "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -8096,8 +8081,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true, - "optional": true + "dev": true } } }, diff --git a/allure-generator/src/main/java/io/qameta/allure/ConfigurationBuilder.java b/allure-generator/src/main/java/io/qameta/allure/ConfigurationBuilder.java index 8d2a4413b..174eb89f7 100644 --- a/allure-generator/src/main/java/io/qameta/allure/ConfigurationBuilder.java +++ b/allure-generator/src/main/java/io/qameta/allure/ConfigurationBuilder.java @@ -36,6 +36,7 @@ import io.qameta.allure.ga.GaPlugin; import io.qameta.allure.history.HistoryPlugin; import io.qameta.allure.history.HistoryTrendPlugin; +import io.qameta.allure.hotspot.HotspotPlugin; import io.qameta.allure.idea.IdeaLinksPlugin; import io.qameta.allure.influxdb.InfluxDbExportPlugin; import io.qameta.allure.launch.LaunchPlugin; @@ -107,7 +108,8 @@ public ConfigurationBuilder useDefault() { new Allure1Plugin(), new Allure1EnvironmentPlugin(), new Allure2Plugin(), - new GaPlugin() + new GaPlugin(), + new HotspotPlugin() )); return this; } diff --git a/allure-generator/src/main/java/io/qameta/allure/hotspot/Element.java b/allure-generator/src/main/java/io/qameta/allure/hotspot/Element.java new file mode 100644 index 000000000..76111161f --- /dev/null +++ b/allure-generator/src/main/java/io/qameta/allure/hotspot/Element.java @@ -0,0 +1,44 @@ +package io.qameta.allure.hotspot; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * @author eroshenkoam (Artem Eroshenko). + */ +@Data +@Accessors(chain = true) +public class Element { + + private String fullPath; + private int count; + private Set urls = new HashSet<>(); + private List tests = new ArrayList<>(); + + public Element addUrls(final Set url) { + urls.addAll(url); + return this; + } + + + /** + * @author eroshenkoam (Artem Eroshenko). + */ + @Data + @Accessors(chain = true) + public static class Test { + + private String uid; + private String name; + private String url; + private String status; + private Long duration; + + } + +} diff --git a/allure-generator/src/main/java/io/qameta/allure/hotspot/HotspotPlugin.java b/allure-generator/src/main/java/io/qameta/allure/hotspot/HotspotPlugin.java new file mode 100644 index 000000000..b0987c7e1 --- /dev/null +++ b/allure-generator/src/main/java/io/qameta/allure/hotspot/HotspotPlugin.java @@ -0,0 +1,131 @@ +package io.qameta.allure.hotspot; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import freemarker.template.utility.StringUtil; +import io.qameta.allure.Aggregator; +import io.qameta.allure.core.Configuration; +import io.qameta.allure.core.LaunchResults; +import io.qameta.allure.entity.Attachment; +import io.qameta.allure.entity.ExecutorInfo; +import io.qameta.allure.entity.StageResult; +import io.qameta.allure.entity.Step; +import io.qameta.allure.executor.ExecutorPlugin; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * @author eroshenkoam (Artem Eroshenko). + */ +@SuppressWarnings({ + "PMD.SystemPrintln", + "PMD.AvoidInstantiatingObjectsInLoops", + "PMD.AvoidThrowingRawExceptionTypes", + "ExecutableStatementCount" +}) +public class HotspotPlugin implements Aggregator { + + @Override + public void aggregate(final Configuration configuration, + final List launchesResults, + final Path outputDirectory) throws IOException { + final ObjectMapper mapper = new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + final Map elements = new HashMap<>(); + launchesResults.forEach(launch -> { + final ExecutorInfo executor = launch.getExtra( + ExecutorPlugin.EXECUTORS_BLOCK_NAME, + ExecutorInfo::new + ); + launch.getAllResults().stream().filter(s -> !s.isHidden()).forEach(result -> { + final List attachments = new ArrayList<>(); + result.getBeforeStages().stream() + .filter(Objects::nonNull) + .map(this::getAttachments) + .forEach(attachments::addAll); + result.getAfterStages().stream() + .filter(Objects::nonNull) + .map(this::getAttachments) + .forEach(attachments::addAll); + Optional.ofNullable(result.getTestStage()) + .map(this::getAttachments) + .ifPresent(attachments::addAll); + + final List locators = attachments.stream() + .filter(attachment -> attachment.getName().endsWith("locators2")) + .collect(Collectors.toList()); + + for (final Attachment attachment : locators) { + try { + final Path path = outputDirectory.resolve("data").resolve("attachments") + .resolve(attachment.getSource()); + final List actions = mapper + .readValue(path.toFile(), new TypeReference>() { + }); + actions.forEach(action -> { + if (StringUtil.isTrimmableToEmpty(action.getFullPath().toCharArray())) { + return; + } + final Element element = elements.getOrDefault(action.getFullPath(), new Element()); + element.setFullPath(action.getFullPath()); + element.addUrls(action.getUrls()); + + final String uuid = result.getUid(); + final boolean exists = element.getTests().stream() + .map(Element.Test::getUid) + .anyMatch(uuid::equals); + if (!exists) { + final Element.Test test = new Element.Test() + .setUid(result.getUid()) + .setName(result.getName()) + .setDuration(result.getTime().getDuration()) + .setStatus(result.getStatus().value()); + Optional.ofNullable(executor) + .map(ExecutorInfo::getReportUrl) + .map(url -> this.createReportUrl(url, result.getUid())) + .ifPresent(test::setUrl); + element.getTests().add(test); + } + element.setCount(element.getTests().size()); + elements.put(element.getFullPath(), element); + }); + } catch (IOException e) { + e.printStackTrace(System.out); +// throw new RuntimeException(e); + } + } + }); + }); + final Path hotspot = outputDirectory.resolve("export").resolve("hotspot.json"); + Files.write(hotspot, mapper.writeValueAsBytes(elements.values())); + } + + private List getAttachments(final StageResult stage) { + final List attachments = new ArrayList<>(); + Optional.ofNullable(stage.getAttachments()).ifPresent(attachments::addAll); + stage.getSteps().forEach(step -> attachments.addAll(getAttachments(step))); + return attachments; + } + + private List getAttachments(final Step steps) { + final List attachments = new ArrayList<>(); + Optional.ofNullable(steps.getAttachments()).ifPresent(attachments::addAll); + steps.getSteps().forEach(step -> attachments.addAll(getAttachments(step))); + return attachments; + } + + private String createReportUrl(final String reportUrl, final String uuid) { + final String pattern = reportUrl.endsWith("index.html") ? "%s#testresult/%s" : "%s/#testresult/%s"; + return String.format(pattern, reportUrl, uuid); + } +} diff --git a/allure-generator/src/main/java/io/qameta/allure/hotspot/LocatorAction.java b/allure-generator/src/main/java/io/qameta/allure/hotspot/LocatorAction.java new file mode 100644 index 000000000..3c2894b26 --- /dev/null +++ b/allure-generator/src/main/java/io/qameta/allure/hotspot/LocatorAction.java @@ -0,0 +1,19 @@ +package io.qameta.allure.hotspot; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.HashSet; +import java.util.Set; + +/** + * @author eroshenkoam (Artem Eroshenko). + */ +@Data +@Accessors(chain = true) +public class LocatorAction { + + private String fullPath; + private Set urls = new HashSet<>(); + +} diff --git a/hotspot.sh b/hotspot.sh new file mode 100755 index 000000000..7f022ba0f --- /dev/null +++ b/hotspot.sh @@ -0,0 +1,2 @@ +./allure-commandline/build/install/allure-commandline/bin/allure serve --port 3333 \ + /Users/eroshenkoam/Downloads/realty/realty-web-tests/target/allure-results