Skip to content

Commit 84c6372

Browse files
committed
#2541 Capture all system.out messages into the extent report
1 parent 959a5e4 commit 84c6372

File tree

2 files changed

+126
-4
lines changed

2 files changed

+126
-4
lines changed

jme3-screenshot-tests/src/main/java/org/jmonkeyengine/screenshottests/testframework/ExtentReportExtension.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
*/
5151
public class ExtentReportExtension implements BeforeAllCallback, AfterAllCallback, TestWatcher, BeforeTestExecutionCallback{
5252
private static ExtentReports extent;
53-
private static final ThreadLocal<ExtentTest> test = new ThreadLocal<>();
53+
private static ExtentTest currentTest;
5454

5555
@Override
5656
public void beforeAll(ExtensionContext context) {
@@ -62,6 +62,8 @@ public void beforeAll(ExtensionContext context) {
6262
extent = new ExtentReports();
6363
extent.attachReporter(spark);
6464
}
65+
// Initialize log capture to redirect console output to the report
66+
ExtentReportLogCapture.initialize();
6567
}
6668

6769
@Override
@@ -71,6 +73,9 @@ public void afterAll(ExtensionContext context) {
7173
* anywhere else I can hook into the lifecycle of the end of all tests to write the report.
7274
*/
7375
extent.flush();
76+
77+
// Restore the original System.out
78+
ExtentReportLogCapture.restore();
7479
}
7580

7681
@Override
@@ -96,10 +101,10 @@ public void testDisabled(ExtensionContext context, Optional<String> reason) {
96101
@Override
97102
public void beforeTestExecution(ExtensionContext context) {
98103
String testName = context.getDisplayName();
99-
test.set(extent.createTest(testName));
104+
currentTest = extent.createTest(testName);
100105
}
101106

102107
public static ExtentTest getCurrentTest() {
103-
return test.get();
108+
return currentTest;
104109
}
105-
}
110+
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
* Copyright (c) 2024 jMonkeyEngine
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are
7+
* met:
8+
*
9+
* * Redistributions of source code must retain the above copyright
10+
* notice, this list of conditions and the following disclaimer.
11+
*
12+
* * Redistributions in binary form must reproduce the above copyright
13+
* notice, this list of conditions and the following disclaimer in the
14+
* documentation and/or other materials provided with the distribution.
15+
*
16+
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17+
* may be used to endorse or promote products derived from this software
18+
* without specific prior written permission.
19+
*
20+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22+
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25+
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27+
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28+
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29+
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31+
*/
32+
package org.jmonkeyengine.screenshottests.testframework;
33+
34+
import com.aventstack.extentreports.ExtentTest;
35+
36+
import java.io.OutputStream;
37+
import java.io.PrintStream;
38+
39+
/**
40+
* This class captures console logs and adds them to the ExtentReport.
41+
* It redirects System.out to both the original console and the ExtentReport.
42+
*
43+
* @author Richard Tingle (aka richtea)
44+
*/
45+
public class ExtentReportLogCapture {
46+
47+
private static final PrintStream originalOut = System.out;
48+
private static final PrintStream originalErr = System.err;
49+
private static boolean initialized = false;
50+
51+
/**
52+
* Initializes the log capture system. This should be called once at the start of the test suite.
53+
*/
54+
public static void initialize() {
55+
if (!initialized) {
56+
// Redirect System.out and System.err
57+
System.setOut(new ExtentReportPrintStream(originalOut));
58+
System.setErr(new ExtentReportPrintStream(originalErr));
59+
60+
initialized = true;
61+
}
62+
}
63+
64+
/**
65+
* Restores the original System.out. This should be called at the end of the test suite.
66+
*/
67+
public static void restore() {
68+
if(initialized) {
69+
// Restore System.out and System.err
70+
System.setOut(originalOut);
71+
System.setErr(originalErr);
72+
initialized = false;
73+
}
74+
}
75+
76+
/**
77+
* A custom PrintStream that redirects output to both the original console and the ExtentReport.
78+
*/
79+
private static class ExtentReportPrintStream extends PrintStream {
80+
private StringBuilder buffer = new StringBuilder();
81+
82+
public ExtentReportPrintStream(OutputStream out) {
83+
super(out, true);
84+
}
85+
86+
@Override
87+
public void write(byte[] buf, int off, int len) {
88+
super.write(buf, off, len);
89+
90+
// Convert the byte array to a string and add to buffer
91+
String s = new String(buf, off, len);
92+
buffer.append(s);
93+
94+
// If we have a complete line (ends with newline), process it
95+
if (s.endsWith("\n") || s.endsWith("\r\n")) {
96+
String line = buffer.toString().trim();
97+
if (!line.isEmpty()) {
98+
addToExtentReport(line);
99+
}
100+
buffer.setLength(0); // Clear the buffer
101+
}
102+
}
103+
104+
private void addToExtentReport(String s) {
105+
try {
106+
ExtentTest currentTest = ExtentReportExtension.getCurrentTest();
107+
if (currentTest != null) {
108+
currentTest.info(s);
109+
}
110+
} catch (Exception e) {
111+
// If there's an error adding to the report, just continue
112+
// This ensures that console logs are still displayed even if there's an issue with the report
113+
}
114+
}
115+
}
116+
117+
}

0 commit comments

Comments
 (0)