Skip to content

Commit d41cb16

Browse files
committed
Improve Robolectric UI test diagnostics
1 parent bda6904 commit d41cb16

File tree

2 files changed

+90
-8
lines changed

2 files changed

+90
-8
lines changed

scripts/build-android-app.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,13 @@ if [ "$TEST_EXIT_CODE" -ne 0 ]; then
365365
if [ -d "$TEST_RESULTS_DIR" ]; then
366366
ba_log "Available XML results under $TEST_RESULTS_DIR:"
367367
find "$TEST_RESULTS_DIR" -maxdepth 1 -type f -name '*.xml' -print | sed 's#^.*/##' | sed 's/^/[build-android-app] /'
368+
shopt -s nullglob
369+
for result_xml in "$TEST_RESULTS_DIR"/*.xml; do
370+
ba_log "----- Begin test result XML: $(basename "$result_xml") -----"
371+
sed 's/^/[build-android-app] | /' "$result_xml"
372+
ba_log "----- End test result XML: $(basename "$result_xml") -----"
373+
done
374+
shopt -u nullglob
368375
else
369376
ba_log "No test result XML directory found at $TEST_RESULTS_DIR"
370377
fi

scripts/templates/HelloCodenameOneUiTest.java.tmpl

Lines changed: 83 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,17 @@ import java.io.FileOutputStream;
1414
import java.io.FileWriter;
1515
import java.io.IOException;
1616
import java.io.PrintWriter;
17+
import java.io.StringWriter;
1718
import java.util.concurrent.TimeUnit;
1819
import org.junit.After;
1920
import org.junit.Before;
2021
import org.junit.Rule;
2122
import org.junit.Test;
2223
import org.junit.rules.TestRule;
2324
import org.junit.rules.Timeout;
25+
import org.junit.rules.TestWatcher;
2426
import org.junit.runner.RunWith;
27+
import org.junit.runner.Description;
2528
import org.robolectric.Robolectric;
2629
import org.robolectric.RobolectricTestRunner;
2730
import org.robolectric.android.controller.ActivityController;
@@ -45,17 +48,58 @@ public class @MAIN_NAME@UiTest {
4548
.withLookingForStuckThread(true)
4649
.build();
4750

51+
@Rule
52+
public final TestWatcher loggingWatcher = new TestWatcher() {
53+
@Override
54+
protected void starting(Description description) {
55+
log("Starting test method: " + description.getDisplayName());
56+
}
57+
58+
@Override
59+
protected void succeeded(Description description) {
60+
log("Test method succeeded: " + description.getDisplayName());
61+
}
62+
63+
@Override
64+
protected void failed(Throwable e, Description description) {
65+
logError("Test method failed: " + description.getDisplayName(), e);
66+
dumpAllThreads("Failure diagnostics for " + description.getDisplayName());
67+
}
68+
69+
@Override
70+
protected void finished(Description description) {
71+
log("Finished test method: " + description.getDisplayName());
72+
}
73+
};
74+
4875
@Before
4976
public void setUp() {
5077
log("Starting Robolectric activity for screenshot test");
51-
controller = Robolectric.buildActivity(@[email protected]);
52-
log("ActivityController created");
78+
try {
79+
controller = Robolectric.buildActivity(@[email protected]);
80+
log("ActivityController created");
81+
} catch (RuntimeException ex) {
82+
logError("Failed to create ActivityController", ex);
83+
throw ex;
84+
}
5385
log("Invoking controller.setup() to create/start/resume activity");
54-
activity = controller.setup().get();
55-
log("controller.setup() completed (Display.isInitialized=" + Display.isInitialized() + ")");
86+
try {
87+
activity = controller.setup().get();
88+
log("controller.setup() completed (Display.isInitialized=" + Display.isInitialized()
89+
+ ", activity=" + activity + ")");
90+
} catch (RuntimeException ex) {
91+
logError("controller.setup() threw an exception", ex);
92+
dumpAllThreads("controller.setup() failure diagnostics");
93+
throw ex;
94+
}
5695
log("Processing pending Codename One tasks after setup");
57-
ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
58-
log("Initial runUiThreadTasksIncludingDelayedTasks call finished");
96+
try {
97+
ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
98+
log("Initial runUiThreadTasksIncludingDelayedTasks call finished");
99+
} catch (RuntimeException ex) {
100+
logError("runUiThreadTasksIncludingDelayedTasks threw an exception", ex);
101+
throw ex;
102+
}
59103
}
60104

61105
@After
@@ -72,8 +116,13 @@ public class @MAIN_NAME@UiTest {
72116
public void mainFormScreenshotContainsRenderedContent() throws Exception {
73117
log("Running screenshot assertions with prepared activity");
74118
log("Idling main looper to process pending tasks");
75-
ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
76-
log("Completed runUiThreadTasksIncludingDelayedTasks");
119+
try {
120+
ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
121+
log("Completed runUiThreadTasksIncludingDelayedTasks");
122+
} catch (RuntimeException ex) {
123+
logError("runUiThreadTasksIncludingDelayedTasks during test threw an exception", ex);
124+
throw ex;
125+
}
77126

78127
if (Display.isInitialized()) {
79128
log("Codename One display reports current form="
@@ -189,6 +238,17 @@ public class @MAIN_NAME@UiTest {
189238
appendLogLine(formatted);
190239
}
191240

241+
private static void logError(String message, Throwable error) {
242+
log(message + ": " + error);
243+
StringWriter buffer = new StringWriter();
244+
error.printStackTrace(new PrintWriter(buffer));
245+
for (String line : buffer.toString().split("\r?\n")) {
246+
if (!line.isEmpty()) {
247+
log(line);
248+
}
249+
}
250+
}
251+
192252
private static void safelyInvokeLifecycle(Runnable invocation, String name) {
193253
try {
194254
invocation.run();
@@ -210,4 +270,19 @@ public class @MAIN_NAME@UiTest {
210270
System.out.println("[@MAIN_NAME@UiTest] Failed to persist log entry: " + ex.getMessage());
211271
}
212272
}
273+
274+
private static void dumpAllThreads(String reason) {
275+
log("Capturing thread dump: " + reason);
276+
Thread.getAllStackTraces().forEach((thread, stack) -> {
277+
log("Thread '" + thread.getName() + "' (id=" + thread.getId()
278+
+ ", state=" + thread.getState() + ")");
279+
if (stack.length == 0) {
280+
log(" <no stack trace>");
281+
} else {
282+
for (StackTraceElement element : stack) {
283+
log(" at " + element);
284+
}
285+
}
286+
});
287+
}
213288
}

0 commit comments

Comments
 (0)