Add a junit4 rule for OTel testing. (#1996)
* Add a junit4 rule for OTel testing. * Docs to 4 * A bit more 4 * Volatile just in case
This commit is contained in:
parent
d0e0b5a553
commit
f01456bebd
|
|
@ -9,7 +9,9 @@ ext.moduleName = 'io.opentelemetry.sdk.testing'
|
|||
dependencies {
|
||||
api project(':opentelemetry-api')
|
||||
api project(':opentelemetry-sdk')
|
||||
api libraries.junit_jupiter_api
|
||||
|
||||
compileOnly libraries.junit
|
||||
compileOnly libraries.junit_jupiter_api
|
||||
|
||||
annotationProcessor libraries.auto_value
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.testing.junit4;
|
||||
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.api.trace.propagation.HttpTraceContext;
|
||||
import io.opentelemetry.context.propagation.DefaultContextPropagators;
|
||||
import io.opentelemetry.exporter.inmemory.InMemorySpanExporter;
|
||||
import io.opentelemetry.sdk.OpenTelemetrySdk;
|
||||
import io.opentelemetry.sdk.trace.TracerSdkManagement;
|
||||
import io.opentelemetry.sdk.trace.TracerSdkProvider;
|
||||
import io.opentelemetry.sdk.trace.data.SpanData;
|
||||
import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor;
|
||||
import java.util.List;
|
||||
import org.junit.rules.ExternalResource;
|
||||
|
||||
/**
|
||||
* A JUnit4 rule which sets up the {@link OpenTelemetrySdk} for testing, resetting state between
|
||||
* tests. This rule cannot be used with {@link org.junit.ClassRule}.
|
||||
*
|
||||
* <pre>{@code
|
||||
* > public class CoolTest {
|
||||
* > {@literal @}Rule
|
||||
* > public OpenTelemetryExtension otelTesting = OpenTelemetryExtension.create();
|
||||
* >
|
||||
* > private Tracer tracer;
|
||||
* >
|
||||
* > {@literal @}Before
|
||||
* > public void setUp() {
|
||||
* > tracer = otelTesting.getOpenTelemetry().getTracer("test");
|
||||
* > }
|
||||
* >
|
||||
* > {@literal @}Test
|
||||
* > public void test() {
|
||||
* > tracer.spanBuilder("name").startSpan().end();
|
||||
* > assertThat(otelTesting.getSpans()).containsExactly(expected);
|
||||
* > }
|
||||
* > }
|
||||
* }</pre>
|
||||
*/
|
||||
public class OpenTelemetryRule extends ExternalResource {
|
||||
|
||||
/**
|
||||
* Returns a {@link OpenTelemetryRule} with a default SDK initialized with an in-memory span
|
||||
* exporter and W3C trace context propagation.
|
||||
*/
|
||||
public static OpenTelemetryRule create() {
|
||||
InMemorySpanExporter spanExporter = InMemorySpanExporter.create();
|
||||
|
||||
TracerSdkProvider tracerProvider = TracerSdkProvider.builder().build();
|
||||
tracerProvider.addSpanProcessor(SimpleSpanProcessor.builder(spanExporter).build());
|
||||
|
||||
OpenTelemetrySdk openTelemetry =
|
||||
OpenTelemetrySdk.builder()
|
||||
.setPropagators(
|
||||
DefaultContextPropagators.builder()
|
||||
.addTextMapPropagator(HttpTraceContext.getInstance())
|
||||
.build())
|
||||
.setTracerProvider(tracerProvider)
|
||||
.build();
|
||||
|
||||
return new OpenTelemetryRule(openTelemetry, spanExporter);
|
||||
}
|
||||
|
||||
private final OpenTelemetrySdk openTelemetry;
|
||||
private final InMemorySpanExporter spanExporter;
|
||||
|
||||
private volatile OpenTelemetry previousGlobalOpenTelemetry;
|
||||
|
||||
private OpenTelemetryRule(OpenTelemetrySdk openTelemetry, InMemorySpanExporter spanExporter) {
|
||||
this.openTelemetry = openTelemetry;
|
||||
this.spanExporter = spanExporter;
|
||||
}
|
||||
|
||||
/** Returns the {@link OpenTelemetrySdk} created by this extension. */
|
||||
public OpenTelemetry getOpenTelemetry() {
|
||||
return openTelemetry;
|
||||
}
|
||||
|
||||
/** Returns the {@link TracerSdkManagement} created by this extension. */
|
||||
public TracerSdkManagement getTracerManagement() {
|
||||
return openTelemetry.getTracerManagement();
|
||||
}
|
||||
|
||||
/** Returns all the exported {@link SpanData} so far. */
|
||||
public List<SpanData> getSpans() {
|
||||
return spanExporter.getFinishedSpanItems();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the collected exported {@link SpanData}. Consider making your test smaller instead of
|
||||
* manually clearing state using this method.
|
||||
*/
|
||||
public void clearSpans() {
|
||||
spanExporter.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void before() throws Throwable {
|
||||
previousGlobalOpenTelemetry = OpenTelemetry.get();
|
||||
OpenTelemetry.set(openTelemetry);
|
||||
clearSpans();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void after() {
|
||||
OpenTelemetry.set(previousGlobalOpenTelemetry);
|
||||
}
|
||||
}
|
||||
|
|
@ -67,7 +67,7 @@ public class OpenTelemetryExtension
|
|||
private final OpenTelemetrySdk openTelemetry;
|
||||
private final InMemorySpanExporter spanExporter;
|
||||
|
||||
private OpenTelemetry previousGlobalOpenTelemetry;
|
||||
private volatile OpenTelemetry previousGlobalOpenTelemetry;
|
||||
|
||||
private OpenTelemetryExtension(
|
||||
OpenTelemetrySdk openTelemetry, InMemorySpanExporter spanExporter) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.testing.junit4;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.api.trace.Tracer;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
public class OpenTelemetryRuleTest {
|
||||
|
||||
@Rule public OpenTelemetryRule otelTesting = OpenTelemetryRule.create();
|
||||
|
||||
private static OpenTelemetry openTelemetryBeforeTest;
|
||||
|
||||
// Class callbacks happen outside the rule so we can verify the restoration behavior in them.
|
||||
@BeforeClass
|
||||
public static void beforeTest() {
|
||||
openTelemetryBeforeTest = OpenTelemetry.get();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterTest() {
|
||||
assertThat(OpenTelemetry.get()).isSameAs(openTelemetryBeforeTest);
|
||||
}
|
||||
|
||||
private Tracer tracer;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
tracer = otelTesting.getOpenTelemetry().getTracer("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exportSpan() {
|
||||
tracer.spanBuilder("test").startSpan().end();
|
||||
|
||||
assertThat(otelTesting.getSpans())
|
||||
.hasOnlyOneElementSatisfying(span -> assertThat(span.getName()).isEqualTo("test"));
|
||||
// Spans cleared between tests, not when retrieving
|
||||
assertThat(otelTesting.getSpans())
|
||||
.hasOnlyOneElementSatisfying(span -> assertThat(span.getName()).isEqualTo("test"));
|
||||
}
|
||||
|
||||
// We have two tests to verify spans get cleared up between tests.
|
||||
@Test
|
||||
public void exportSpanAgain() {
|
||||
tracer.spanBuilder("test").startSpan().end();
|
||||
|
||||
assertThat(otelTesting.getSpans())
|
||||
.hasOnlyOneElementSatisfying(span -> assertThat(span.getName()).isEqualTo("test"));
|
||||
// Spans cleared between tests, not when retrieving
|
||||
assertThat(otelTesting.getSpans())
|
||||
.hasOnlyOneElementSatisfying(span -> assertThat(span.getName()).isEqualTo("test"));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.testing.junit5;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.api.trace.Tracer;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
class OpenTelemetryExtensionTest {
|
||||
|
||||
@RegisterExtension
|
||||
static final OpenTelemetryExtension otelTesting = OpenTelemetryExtension.create();
|
||||
|
||||
private static OpenTelemetry openTelemetryBeforeTest;
|
||||
|
||||
// Class callbacks happen outside the rule so we can verify the restoration behavior in them.
|
||||
@BeforeAll
|
||||
public static void beforeTest() {
|
||||
openTelemetryBeforeTest = OpenTelemetry.get();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void afterTest() {
|
||||
assertThat(OpenTelemetry.get()).isSameAs(openTelemetryBeforeTest);
|
||||
}
|
||||
|
||||
private final Tracer tracer = otelTesting.getOpenTelemetry().getTracer("test");
|
||||
|
||||
@Test
|
||||
public void exportSpan() {
|
||||
tracer.spanBuilder("test").startSpan().end();
|
||||
|
||||
assertThat(otelTesting.getSpans())
|
||||
.hasOnlyOneElementSatisfying(span -> assertThat(span.getName()).isEqualTo("test"));
|
||||
// Spans cleared between tests, not when retrieving
|
||||
assertThat(otelTesting.getSpans())
|
||||
.hasOnlyOneElementSatisfying(span -> assertThat(span.getName()).isEqualTo("test"));
|
||||
}
|
||||
|
||||
// We have two tests to verify spans get cleared up between tests.
|
||||
@Test
|
||||
public void exportSpanAgain() {
|
||||
tracer.spanBuilder("test").startSpan().end();
|
||||
|
||||
assertThat(otelTesting.getSpans())
|
||||
.hasOnlyOneElementSatisfying(span -> assertThat(span.getName()).isEqualTo("test"));
|
||||
// Spans cleared between tests, not when retrieving
|
||||
assertThat(otelTesting.getSpans())
|
||||
.hasOnlyOneElementSatisfying(span -> assertThat(span.getName()).isEqualTo("test"));
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue