Skip to content

Commit 4bd41c7

Browse files
committed
improve assertions by showing the last result on a timeout
1 parent 3b267cb commit 4bd41c7

File tree

3 files changed

+75
-47
lines changed

3 files changed

+75
-47
lines changed

testing-common/src/main/java/io/opentelemetry/instrumentation/testing/InstrumentationTestRunner.java

+27-41
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
package io.opentelemetry.instrumentation.testing;
77

88
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
9-
import static org.awaitility.Awaitility.await;
109

1110
import io.opentelemetry.api.OpenTelemetry;
11+
import io.opentelemetry.instrumentation.testing.internal.AwaitUtil;
1212
import io.opentelemetry.instrumentation.testing.util.TelemetryDataUtil;
1313
import io.opentelemetry.instrumentation.testing.util.ThrowingRunnable;
1414
import io.opentelemetry.instrumentation.testing.util.ThrowingSupplier;
@@ -29,7 +29,6 @@
2929
import java.util.stream.Collectors;
3030
import javax.annotation.Nullable;
3131
import org.assertj.core.api.ListAssert;
32-
import org.awaitility.core.ConditionTimeoutException;
3332

3433
/**
3534
* This interface defines a common set of operations for interaction with OpenTelemetry SDK and
@@ -118,25 +117,8 @@ private <T extends Consumer<TraceAssert>> void waitAndAssertTraces(
118117
List<T> assertionsList = new ArrayList<>();
119118
assertions.forEach(assertionsList::add);
120119

121-
try {
122-
await()
123-
.untilAsserted(() -> doAssertTraces(traceComparator, assertionsList, verifyScopeVersion));
124-
} catch (Throwable t) {
125-
// awaitility is doing a jmx call that is not implemented in GraalVM:
126-
// call:
127-
// https://github.com/awaitility/awaitility/blob/fbe16add874b4260dd240108304d5c0be84eabc8/awaitility/src/main/java/org/awaitility/core/ConditionAwaiter.java#L157
128-
// see https://github.com/oracle/graal/issues/6101 (spring boot graal native image)
129-
if (t.getClass().getName().equals("com.oracle.svm.core.jdk.UnsupportedFeatureError")
130-
|| t instanceof ConditionTimeoutException) {
131-
// Don't throw this failure since the stack is the awaitility thread, causing confusion.
132-
// Instead, just assert one more time on the test thread, which will fail with a better
133-
// stack trace.
134-
// TODO: There is probably a better way to do this.
135-
doAssertTraces(traceComparator, assertionsList, verifyScopeVersion);
136-
} else {
137-
throw t;
138-
}
139-
}
120+
AwaitUtil.awaitUntilAsserted(
121+
() -> doAssertTraces(traceComparator, assertionsList, verifyScopeVersion));
140122
}
141123

142124
private <T extends Consumer<TraceAssert>> void doAssertTraces(
@@ -159,31 +141,35 @@ private <T extends Consumer<TraceAssert>> void doAssertTraces(
159141
*/
160142
public final void waitAndAssertMetrics(
161143
String instrumentationName, String metricName, Consumer<ListAssert<MetricData>> assertion) {
162-
await()
163-
.untilAsserted(
164-
() ->
165-
assertion.accept(
166-
assertThat(getExportedMetrics())
167-
.filteredOn(
168-
data ->
169-
data.getInstrumentationScopeInfo()
170-
.getName()
171-
.equals(instrumentationName)
172-
&& data.getName().equals(metricName))));
144+
145+
AwaitUtil.awaitUntilAsserted(
146+
() ->
147+
assertion.accept(
148+
assertThat(getExportedMetrics())
149+
.describedAs(
150+
"Metrics for instrumentation %s and metric name %s",
151+
instrumentationName, metricName)
152+
.filteredOn(
153+
data ->
154+
data.getInstrumentationScopeInfo().getName().equals(instrumentationName)
155+
&& data.getName().equals(metricName))));
173156
}
174157

175158
@SafeVarargs
176159
public final void waitAndAssertMetrics(
177160
String instrumentationName, Consumer<MetricAssert>... assertions) {
178-
await()
179-
.untilAsserted(
180-
() -> {
181-
Collection<MetricData> metrics = instrumentationMetrics(instrumentationName);
182-
assertThat(metrics).isNotEmpty();
183-
for (Consumer<MetricAssert> assertion : assertions) {
184-
assertThat(metrics).anySatisfy(metric -> assertion.accept(assertThat(metric)));
185-
}
186-
});
161+
AwaitUtil.awaitUntilAsserted(
162+
() -> {
163+
Collection<MetricData> metrics = instrumentationMetrics(instrumentationName);
164+
assertThat(metrics).isNotEmpty();
165+
for (int i = 0; i < assertions.length; i++) {
166+
int index = i;
167+
assertThat(metrics)
168+
.describedAs(
169+
"Metrics for instrumentation %s and assertion %d", instrumentationName, index)
170+
.anySatisfy(metric -> assertions[index].accept(assertThat(metric)));
171+
}
172+
});
187173
}
188174

189175
private List<MetricData> instrumentationMetrics(String instrumentationName) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.testing.internal;
7+
8+
import static org.awaitility.Awaitility.await;
9+
10+
import org.awaitility.core.ConditionFactory;
11+
import org.awaitility.core.ConditionTimeoutException;
12+
13+
/**
14+
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
15+
* any time.
16+
*/
17+
public class AwaitUtil {
18+
private AwaitUtil() {}
19+
20+
public static void awaitUntilAsserted(Runnable runnable) {
21+
awaitUntilAsserted(runnable, await());
22+
}
23+
24+
public static void awaitUntilAsserted(Runnable runnable, ConditionFactory conditionFactory) {
25+
try {
26+
conditionFactory.untilAsserted(runnable::run);
27+
} catch (Throwable t) {
28+
// awaitility is doing a jmx call that is not implemented in GraalVM:
29+
// call:
30+
// https://github.com/awaitility/awaitility/blob/fbe16add874b4260dd240108304d5c0be84eabc8/awaitility/src/main/java/org/awaitility/core/ConditionAwaiter.java#L157
31+
// see https://github.com/oracle/graal/issues/6101 (spring boot graal native image)
32+
if (t.getClass().getName().equals("com.oracle.svm.core.jdk.UnsupportedFeatureError")
33+
|| t instanceof ConditionTimeoutException) {
34+
// Don't throw this failure since the stack is the awaitility thread, causing confusion.
35+
// Instead, just assert one more time on the test thread, which will fail with a better
36+
// stack trace - that is on the same thread as the test.
37+
// TODO: There is probably a better way to do this.
38+
runnable.run();
39+
} else {
40+
throw t;
41+
}
42+
}
43+
}
44+
}

testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/InstrumentationExtension.java

+4-6
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import io.opentelemetry.context.ContextStorage;
1313
import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner;
1414
import io.opentelemetry.instrumentation.testing.LibraryTestRunner;
15+
import io.opentelemetry.instrumentation.testing.internal.AwaitUtil;
1516
import io.opentelemetry.instrumentation.testing.util.ContextStorageCloser;
1617
import io.opentelemetry.instrumentation.testing.util.ThrowingRunnable;
1718
import io.opentelemetry.instrumentation.testing.util.ThrowingSupplier;
@@ -125,12 +126,9 @@ public List<List<SpanData>> waitForTraces(int numberOfTraces) {
125126
* This waits up to 20 seconds, then times out.
126127
*/
127128
public List<LogRecordData> waitForLogRecords(int numberOfLogRecords) {
128-
await()
129-
.timeout(Duration.ofSeconds(20))
130-
.untilAsserted(
131-
() ->
132-
assertThat(testRunner.getExportedLogRecords().size())
133-
.isEqualTo(numberOfLogRecords));
129+
AwaitUtil.awaitUntilAsserted(
130+
() -> assertThat(testRunner.getExportedLogRecords().size()).isEqualTo(numberOfLogRecords),
131+
await().timeout(Duration.ofSeconds(20)));
134132
return testRunner.getExportedLogRecords();
135133
}
136134

0 commit comments

Comments
 (0)