Skip to content

Commit af21457

Browse files
authored
add broken matcher (via #87)
1 parent 147779b commit af21457

File tree

6 files changed

+179
-8
lines changed

6 files changed

+179
-8
lines changed

broken.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"matchers": [
3+
{
4+
"messageRegexp": "Test exceeded execution time allowance of.*"
5+
}
6+
]
7+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package io.eroshenkoam.xcresults.broken;
2+
3+
import java.io.Serializable;
4+
import java.util.List;
5+
6+
public class BrokenConfig implements Serializable {
7+
8+
private List<BrokenStatusMatcher> matchers;
9+
10+
public List<BrokenStatusMatcher> getMatchers() {
11+
return matchers;
12+
}
13+
14+
public void setMatchers(final List<BrokenStatusMatcher> matchers) {
15+
this.matchers = matchers;
16+
}
17+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package io.eroshenkoam.xcresults.broken;
2+
3+
import com.fasterxml.jackson.databind.ObjectMapper;
4+
import com.fasterxml.jackson.databind.SerializationFeature;
5+
import io.eroshenkoam.xcresults.export.ExportPostProcessor;
6+
import io.qameta.allure.model.Status;
7+
import io.qameta.allure.model.StatusDetails;
8+
import io.qameta.allure.model.TestResult;
9+
10+
import java.io.IOException;
11+
import java.nio.file.Files;
12+
import java.nio.file.Path;
13+
import java.util.Map;
14+
import java.util.Objects;
15+
import java.util.Optional;
16+
17+
public class BrokenPostProcessor implements ExportPostProcessor {
18+
19+
private static final ObjectMapper MAPPER = new ObjectMapper()
20+
.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
21+
22+
private final Path configPath;
23+
24+
public BrokenPostProcessor(final String configPath) {
25+
this.configPath = Path.of(configPath).toAbsolutePath();
26+
}
27+
28+
@Override
29+
public void processTestResults(final Path outputPath, final Map<Path, TestResult> testResults) {
30+
System.out.println("Broken test processor enabled");
31+
if (Files.notExists(configPath)) {
32+
System.out.println("Broken test processor config file not found: " + configPath);
33+
return;
34+
}
35+
final Optional<BrokenConfig> config = readConfig(configPath);
36+
if (config.isEmpty()) {
37+
System.out.println("Broken test processor config file is invalid: " + configPath);
38+
return;
39+
}
40+
testResults.forEach((path, testResult) -> updateStatus(path, testResult, config.get()));
41+
}
42+
43+
private void updateStatus(final Path path, final TestResult testResult, final BrokenConfig config) {
44+
if (Objects.nonNull(testResult.getStatus()) && testResult.getStatus().equals(Status.FAILED)) {
45+
final StatusDetails statusDetails = testResult.getStatusDetails();
46+
47+
final String message = Optional.ofNullable(statusDetails.getMessage()).orElse("");
48+
final String trace = Optional.ofNullable(statusDetails.getTrace()).orElse("");
49+
50+
if (isBroken(message, trace, config)) {
51+
testResult.setStatus(Status.BROKEN);
52+
try {
53+
MAPPER.writeValue(path.toFile(), testResult);
54+
} catch (IOException e) {
55+
System.out.println("Can not update broken test status: " + e.getMessage());
56+
}
57+
}
58+
}
59+
}
60+
61+
private static boolean isBroken(final String message, final String trace, final BrokenConfig config) {
62+
for (final BrokenStatusMatcher matcher: config.getMatchers()) {
63+
final boolean messageMatched = Optional.ofNullable(matcher.getMessagePattern())
64+
.map(pattern -> pattern.matcher(message).matches())
65+
.orElse(false);
66+
final boolean traceMatched = Optional.ofNullable(matcher.getTracePattern())
67+
.map(pattern -> pattern.matcher(message).matches())
68+
.orElse(false);
69+
if (messageMatched || traceMatched) {
70+
return true;
71+
}
72+
}
73+
return false;
74+
}
75+
76+
private static Optional<BrokenConfig> readConfig(final Path config) {
77+
try {
78+
return Optional.of(MAPPER.readValue(config.toFile(), BrokenConfig.class));
79+
} catch (IOException e) {
80+
System.out.println("Can not read broken test processor config file:" + e.getMessage());
81+
return Optional.empty();
82+
}
83+
}
84+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package io.eroshenkoam.xcresults.broken;
2+
3+
import java.io.Serializable;
4+
import java.util.Objects;
5+
import java.util.regex.Pattern;
6+
7+
public class BrokenStatusMatcher implements Serializable {
8+
9+
private String messageRegexp;
10+
private Pattern messagePattern;
11+
12+
private String traceRegexp;
13+
private Pattern tracePattern;
14+
15+
public Pattern getMessagePattern() {
16+
return messagePattern;
17+
}
18+
19+
public String getMessageRegexp() {
20+
return messageRegexp;
21+
}
22+
23+
public BrokenStatusMatcher setMessageRegexp(String messageRegexp) {
24+
this.messageRegexp = messageRegexp;
25+
if (Objects.nonNull(messageRegexp)) {
26+
this.messagePattern = Pattern.compile(messageRegexp);
27+
}
28+
return this;
29+
}
30+
31+
public Pattern getTracePattern() {
32+
return tracePattern;
33+
}
34+
35+
public String getTraceRegexp() {
36+
return traceRegexp;
37+
}
38+
39+
public BrokenStatusMatcher setTraceRegexp(String traceRegexp) {
40+
this.traceRegexp = traceRegexp;
41+
if (Objects.nonNull(traceRegexp)) {
42+
this.tracePattern = Pattern.compile(traceRegexp);
43+
}
44+
return this;
45+
}
46+
}

src/main/java/io/eroshenkoam/xcresults/export/ExportCommand.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ public class ExportCommand implements Runnable {
3838
)
3939
protected List<Path> inputPath;
4040

41+
@CommandLine.Option(
42+
names = {"--broken-config-path"},
43+
description = "Broken config path"
44+
)
45+
protected String brokenConfigPath;
46+
4147
@CommandLine.Option(
4248
names = {"-o", "--output"},
4349
description = "Export output directory"
@@ -69,7 +75,7 @@ public void run() {
6975
private void runUnsafe(final Path input, final Path output) throws Exception {
7076
System.out.printf("Export xcresults from [%s] to [%s]\n", input, output);
7177
final ExportProcessor processor = new ExportProcessor(
72-
input, output, addCarouselAttachment, carouselTemplatePath
78+
input, output, brokenConfigPath, addCarouselAttachment, carouselTemplatePath
7379
);
7480
processor.export();
7581
}

src/main/java/io/eroshenkoam/xcresults/export/ExportProcessor.java

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.fasterxml.jackson.databind.ObjectMapper;
55
import com.fasterxml.jackson.databind.SerializationFeature;
66
import freemarker.template.Version;
7+
import io.eroshenkoam.xcresults.broken.BrokenPostProcessor;
78
import io.eroshenkoam.xcresults.carousel.CarouselPostProcessor;
89
import io.qameta.allure.model.ExecutableItem;
910
import io.qameta.allure.model.TestResult;
@@ -67,16 +68,20 @@ public class ExportProcessor {
6768
private final Path inputPath;
6869
private final Path outputPath;
6970

71+
private String brokenConfigPath;
72+
7073
private Boolean addCarouselAttachment;
7174
private String carouselTemplatePath;
7275

7376

7477
public ExportProcessor(final Path inputPath,
7578
final Path outputPath,
79+
final String brokenConfigPath,
7680
final Boolean addCarouselAttachment,
7781
final String carouselTemplatePath) {
7882
this.inputPath = inputPath;
7983
this.outputPath = outputPath;
84+
this.brokenConfigPath = brokenConfigPath;
8085
this.addCarouselAttachment = addCarouselAttachment;
8186
this.carouselTemplatePath = carouselTemplatePath;
8287
}
@@ -142,17 +147,23 @@ public void export() throws Exception {
142147
});
143148
testResults.put(testSummaryPath, testResult);
144149
}
145-
System.out.printf("Export information about %s attachments...%n", attachmentsRefs.size());
146-
for (Map.Entry<String, String> attachment : attachmentsRefs.entrySet()) {
147-
final String attachmentRef = attachment.getValue();
148-
final Path attachmentPath = outputPath.resolve(attachment.getKey());
149-
exportReference(attachmentRef, attachmentPath);
150-
}
150+
// System.out.printf("Export information about %s attachments...%n", attachmentsRefs.size());
151+
// for (Map.Entry<String, String> attachment : attachmentsRefs.entrySet()) {
152+
// final String attachmentRef = attachment.getValue();
153+
// final Path attachmentPath = outputPath.resolve(attachment.getKey());
154+
// exportReference(attachmentRef, attachmentPath);
155+
// }
156+
//
151157
final List<ExportPostProcessor> postProcessors = new ArrayList<>();
152158
if (Objects.nonNull(addCarouselAttachment)) {
153159
postProcessors.add(new CarouselPostProcessor(carouselTemplatePath));
154160
}
155-
postProcessors.forEach(postProcessor -> postProcessor.processTestResults(outputPath, testResults));
161+
if (Objects.nonNull(brokenConfigPath)) {
162+
postProcessors.add(new BrokenPostProcessor(brokenConfigPath));
163+
}
164+
postProcessors.forEach(
165+
postProcessor -> postProcessor.processTestResults(outputPath, testResults)
166+
);
156167
}
157168

158169
private ExportMeta getTestMeta(final ExportMeta meta, final JsonNode testableSummary) {

0 commit comments

Comments
 (0)