diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index 1db07b4c4c..9ed1a60d39 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -22,14 +22,14 @@ ext { kotlin : "1.4.0", coroutines : "1.3.0", springboot : "2.3.1.RELEASE", - // TODO(anuraaga): Switch off of milestones, this version fixes compatibility with Spock Unroll - junit5 : "5.7.0-M1", + junit5 : "5.7.1", checkerFramework : "3.6.1", errorprone : "2.4.0", nullaway : "0.8.0", autoValue : "1.7.4", systemLambda : "1.1.0", - prometheus : "0.9.0" + prometheus : "0.9.0", + assertj : '3.19.0' ] deps = [ @@ -94,5 +94,7 @@ ext { scala : dependencies.create(group: 'org.scala-lang', name: 'scala-library', version: "${versions.scala}"), kotlin : dependencies.create(group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib', version: "${versions.kotlin}"), coroutines : dependencies.create(group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: "${versions.coroutines}"), + junitApi : "org.junit.jupiter:junit-jupiter-api:${versions.junit5}", + assertj : "org.assertj:assertj-core:${versions.assertj}", ] } diff --git a/instrumentation-api/instrumentation-api.gradle b/instrumentation-api/instrumentation-api.gradle index db1b3ca945..a51351bfcf 100644 --- a/instrumentation-api/instrumentation-api.gradle +++ b/instrumentation-api/instrumentation-api.gradle @@ -14,5 +14,5 @@ dependencies { testImplementation project(':testing-common') testImplementation group: 'org.mockito', name: 'mockito-core', version: '3.6.0' - testImplementation group: 'org.assertj', name: 'assertj-core', version: '3.18.1' + testImplementation deps.assertj } diff --git a/instrumentation-core/servlet-2.2/servlet-2.2.gradle b/instrumentation-core/servlet-2.2/servlet-2.2.gradle index 0308dae41a..5d4b79504a 100644 --- a/instrumentation-core/servlet-2.2/servlet-2.2.gradle +++ b/instrumentation-core/servlet-2.2/servlet-2.2.gradle @@ -10,5 +10,5 @@ dependencies { testImplementation group: 'javax.servlet', name: 'servlet-api', version: '2.2' testImplementation group: 'org.mockito', name: 'mockito-core', version: '3.6.0' - testImplementation group: 'org.assertj', name: 'assertj-core', version: '3.18.1' + testImplementation deps.assertj } diff --git a/instrumentation/apache-camel-2.20/javaagent-unittests/apache-camel-2.20-javaagent-unittests.gradle b/instrumentation/apache-camel-2.20/javaagent-unittests/apache-camel-2.20-javaagent-unittests.gradle index dce214ba10..3e4996c722 100644 --- a/instrumentation/apache-camel-2.20/javaagent-unittests/apache-camel-2.20-javaagent-unittests.gradle +++ b/instrumentation/apache-camel-2.20/javaagent-unittests/apache-camel-2.20-javaagent-unittests.gradle @@ -8,5 +8,5 @@ dependencies { testImplementation deps.opentelemetryTraceProps testImplementation deps.opentelemetryExtAws - testImplementation group: 'org.assertj', name: 'assertj-core', version: '3.18.1' + testImplementation deps.assertj } diff --git a/instrumentation/aws-lambda-1.0/library/aws-lambda-1.0-library.gradle b/instrumentation/aws-lambda-1.0/library/aws-lambda-1.0-library.gradle index 9a721458b2..541302107e 100644 --- a/instrumentation/aws-lambda-1.0/library/aws-lambda-1.0-library.gradle +++ b/instrumentation/aws-lambda-1.0/library/aws-lambda-1.0-library.gradle @@ -46,5 +46,5 @@ dependencies { testImplementation project(':instrumentation:aws-lambda-1.0:testing') testImplementation group: 'org.mockito', name: 'mockito-core', version: '3.6.0' - testImplementation group: 'org.assertj', name: 'assertj-core', version: '3.18.1' + testImplementation deps.assertj } diff --git a/instrumentation/oshi/library/oshi-library.gradle b/instrumentation/oshi/library/oshi-library.gradle index 69e9bc10eb..f654b5b683 100644 --- a/instrumentation/oshi/library/oshi-library.gradle +++ b/instrumentation/oshi/library/oshi-library.gradle @@ -8,5 +8,5 @@ dependencies { testImplementation deps.opentelemetrySdkMetrics testImplementation project(':testing-common') - testImplementation group: 'org.assertj', name: 'assertj-core', version: '3.18.1' + testImplementation deps.assertj } \ No newline at end of file diff --git a/javaagent-api/javaagent-api.gradle b/javaagent-api/javaagent-api.gradle index 878975b2e5..accc2fbb9e 100644 --- a/javaagent-api/javaagent-api.gradle +++ b/javaagent-api/javaagent-api.gradle @@ -28,7 +28,7 @@ dependencies { testImplementation project(':testing-common') testImplementation group: 'org.mockito', name: 'mockito-core', version: '3.6.0' - testImplementation group: 'org.assertj', name: 'assertj-core', version: '3.18.1' + testImplementation deps.assertj } sourcesJar { diff --git a/javaagent-bootstrap/javaagent-bootstrap.gradle b/javaagent-bootstrap/javaagent-bootstrap.gradle index 62b4c79654..d2d5cb28f2 100644 --- a/javaagent-bootstrap/javaagent-bootstrap.gradle +++ b/javaagent-bootstrap/javaagent-bootstrap.gradle @@ -29,5 +29,5 @@ dependencies { testImplementation project(':testing-common') testImplementation group: 'org.mockito', name: 'mockito-core', version: '3.6.0' - testImplementation group: 'org.assertj', name: 'assertj-core', version: '3.18.1' + testImplementation deps.assertj } diff --git a/javaagent-tooling/javaagent-tooling.gradle b/javaagent-tooling/javaagent-tooling.gradle index 2a6047ca76..d97adef538 100644 --- a/javaagent-tooling/javaagent-tooling.gradle +++ b/javaagent-tooling/javaagent-tooling.gradle @@ -64,7 +64,7 @@ dependencies { implementation group: 'io.grpc', name: 'grpc-netty', version: '1.34.1' testImplementation project(':testing-common') - testImplementation group: 'org.assertj', name: 'assertj-core', version: '3.18.1' + testImplementation deps.assertj testImplementation group: 'org.mockito', name: 'mockito-core', version: '3.6.0' instrumentationMuzzle sourceSets.main.output diff --git a/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/AgentInstrumentationExtension.java b/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/AgentInstrumentationExtension.java new file mode 100644 index 0000000000..079a01eaaa --- /dev/null +++ b/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/AgentInstrumentationExtension.java @@ -0,0 +1,41 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.testing.junit; + +import io.opentelemetry.instrumentation.testing.AgentTestRunner; + +/** + * JUnit 5 extension for writing javaagent instrumentation tests. + * + *

Example usage: + * + *

+ *   class MyAgentInstrumentationTest {
+ *     {@literal @}RegisterExtension
+ *     static final AgentInstrumentationExtension instrTesting = AgentInstrumentationExtension.create();
+ *
+ *     {@literal @}Test
+ *     void test() {
+ *       // test code ...
+ *
+ *       var spans = instrTesting.spans();
+ *       // assertions on collected spans ...
+ *     }
+ *   }
+ * 
+ * + *

Note that {@link AgentInstrumentationExtension} will not work by itself, you have to run the + * tests process with the {@code agent-for-testing} javaagent. + */ +public final class AgentInstrumentationExtension extends InstrumentationExtension { + private AgentInstrumentationExtension() { + super(AgentTestRunner.instance()); + } + + public static AgentInstrumentationExtension create() { + return new AgentInstrumentationExtension(); + } +} diff --git a/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/InstrumentationExtension.java b/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/InstrumentationExtension.java new file mode 100644 index 0000000000..ac6fec2f21 --- /dev/null +++ b/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/InstrumentationExtension.java @@ -0,0 +1,47 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.testing.junit; + +import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner; +import io.opentelemetry.sdk.metrics.data.MetricData; +import io.opentelemetry.sdk.trace.data.SpanData; +import java.util.List; +import org.junit.jupiter.api.extension.AfterAllCallback; +import org.junit.jupiter.api.extension.BeforeAllCallback; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; + +public abstract class InstrumentationExtension + implements BeforeAllCallback, BeforeEachCallback, AfterAllCallback { + private final InstrumentationTestRunner testRunner; + + protected InstrumentationExtension(InstrumentationTestRunner testRunner) { + this.testRunner = testRunner; + } + + @Override + public void beforeAll(ExtensionContext extensionContext) { + testRunner.beforeTestClass(); + } + + @Override + public void beforeEach(ExtensionContext extensionContext) { + testRunner.clearAllExportedData(); + } + + @Override + public void afterAll(ExtensionContext extensionContext) { + testRunner.beforeTestClass(); + } + + public List spans() { + return testRunner.getExportedSpans(); + } + + public List metrics() { + return testRunner.getExportedMetrics(); + } +} diff --git a/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/LibraryInstrumentationExtension.java b/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/LibraryInstrumentationExtension.java new file mode 100644 index 0000000000..822eb71748 --- /dev/null +++ b/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/LibraryInstrumentationExtension.java @@ -0,0 +1,38 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.testing.junit; + +import io.opentelemetry.instrumentation.testing.LibraryTestRunner; + +/** + * JUnit 5 extension for writing library instrumentation tests. + * + *

Example usage: + * + *

+ *   class MyLibraryInstrumentationTest {
+ *     {@literal @}RegisterExtension
+ *     static final LibraryInstrumentationExtension instrTesting = LibraryInstrumentationExtension.create();
+ *
+ *     {@literal @}Test
+ *     void test() {
+ *       // test code ...
+ *
+ *       var spans = instrTesting.spans();
+ *       // assertions on collected spans ...
+ *     }
+ *   }
+ * 
+ */ +public final class LibraryInstrumentationExtension extends InstrumentationExtension { + private LibraryInstrumentationExtension() { + super(LibraryTestRunner.instance()); + } + + public static LibraryInstrumentationExtension create() { + return new LibraryInstrumentationExtension(); + } +} diff --git a/testing-common/src/test/java/io/opentelemetry/instrumentation/testing/junit/LibraryInstrumentationExtensionTest.java b/testing-common/src/test/java/io/opentelemetry/instrumentation/testing/junit/LibraryInstrumentationExtensionTest.java new file mode 100644 index 0000000000..307064322a --- /dev/null +++ b/testing-common/src/test/java/io/opentelemetry/instrumentation/testing/junit/LibraryInstrumentationExtensionTest.java @@ -0,0 +1,33 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.testing.junit; + +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import io.opentelemetry.instrumentation.test.utils.TraceUtils; +import io.opentelemetry.sdk.trace.data.SpanData; +import java.util.List; +import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.extension.RegisterExtension; + +class LibraryInstrumentationExtensionTest { + @RegisterExtension + static final LibraryInstrumentationExtension instrumentation = + LibraryInstrumentationExtension.create(); + + // repeated test verifies that the telemetry data is cleared between test runs + @RepeatedTest(5) + void shouldCollectTraces() { + // when + TraceUtils.runInternalSpan("test"); + + // then + List spans = instrumentation.spans(); + assertEquals(1, spans.size()); + assertThat(spans.get(0)).hasName("test"); + } +} diff --git a/testing-common/testing-common.gradle b/testing-common/testing-common.gradle index b8b61d1b32..2980d9c55b 100644 --- a/testing-common/testing-common.gradle +++ b/testing-common/testing-common.gradle @@ -7,6 +7,7 @@ apply from: "$rootDir/gradle/publish.gradle" dependencies { api deps.groovy api deps.spock + implementation deps.junitApi api deps.opentelemetryApi api deps.opentelemetrySdk @@ -32,6 +33,8 @@ dependencies { annotationProcessor deps.autoservice compileOnly deps.autoservice + testImplementation deps.assertj + testImplementation project(':instrumentation-api') testImplementation project(':javaagent-api') testImplementation project(':javaagent-tooling')