Skip to content

Add smoke test JUnit framework - #12111

Open
PerfectSlayer wants to merge 1 commit into
masterfrom
bbujon/smoke-tests-junit-framework
Open

Add smoke test JUnit framework#12111
PerfectSlayer wants to merge 1 commit into
masterfrom
bbujon/smoke-tests-junit-framework

Conversation

@PerfectSlayer

@PerfectSlayer PerfectSlayer commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

What Does This Do

This PR adds a JUnit 5 / Java smoke test framework that allows to write smoke tests using Java/JUnit 5 instead of Groovy/Spock.

The framework has four parts:

  • App runners: AbstractSmokeApp with SmokeServerApp (long-running/HTTP) and
    SmokeCliApp (batch) concrete types, registered as a @RegisterExtension.
    Owns the launched app's lifecycle and wires in the agent jar + test agent session token.

  • Backends: a common TraceBackend facade with two interchangeable implementations:
    MockAgentBackend (in-process JavaTestHttpServer, no Docker) and TestAgentBackend
    (a Testcontainers-managed, or external/CI, dd-apm-test-agent, scoped per test via
    X-Datadog-Test-Session-Token).
    A test written against the facade runs unchanged on either backend but the goal is moving toward TestAgentBackend by default.

  • Capture surfaces: Traces (msgpack/JSON decoded through the shared decoder), Logs (std out/error logs with clear, waitFor capabilities),Telemetry (with message-batch flattening), and RemoteConfig (push a config the
    tracer polls for, and read back its /v0.7/config polls, with products/capabilities
    decoders).
    Traces, telemetry, and remote config are all isolated per test for owned backends.

Motivation

The goal is to provide framework for testing tracing instrumentations and products.
Unlike the existing solution, it verifies the signals against an agent, not our our decoders, and it no longer relies on Groovy / Spock but Java and JUnit.

Additional Notes

Contributor Checklist

Jira ticket: APMLP-1247

@PerfectSlayer PerfectSlayer added type: feature Enhancements and improvements comp: testing Testing tag: ai generated Largely based on code generated by an AI or LLM labels Jul 30, 2026
@dd-octo-sts

dd-octo-sts Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

🟢 Java Benchmark SLOs — All performance SLOs passed

Suite Status
Startup 🟢 pass

SLO thresholds are defined here based on automatically generated metrics. A warning is raised when results are within 5% of the threshold.

PR vs. master results
Scenario Candidate master Δ (95% CI of mean)
startup:insecure-bank:iast:Agent 14.87 s 14.77 s [-0.3%; +1.7%] (no difference)
startup:insecure-bank:tracing:Agent 13.58 s 13.72 s [-1.9%; -0.1%] (maybe better)
startup:petclinic:appsec:Agent 16.84 s 16.69 s [-0.2%; +2.0%] (no difference)
startup:petclinic:iast:Agent 16.84 s 16.54 s [-2.8%; +6.4%] (no difference)
startup:petclinic:profiling:Agent 16.81 s 16.75 s [-0.7%; +1.4%] (no difference)
startup:petclinic:sca:Agent 16.32 s 16.67 s [-6.5%; +2.3%] (no difference)
startup:petclinic:tracing:Agent 16.03 s 16.19 s [-1.7%; -0.2%] (maybe better)

Commit: 0f9f7043 · CI Pipeline · Benchmarking Platform UI


Load and DaCapo benchmarks can be triggered manually in the GitLab pipeline. Results will appear in the Benchmarking Platform UI after completion.

Base automatically changed from bbujon/smoke-tests-decoded-span-assertions to master July 31, 2026 06:04
@PerfectSlayer
PerfectSlayer force-pushed the bbujon/smoke-tests-junit-framework branch from 4a50f04 to 11530c9 Compare July 31, 2026 08:46
@datadog-datadog-us1-prod

datadog-datadog-us1-prod Bot commented Jul 31, 2026

Copy link
Copy Markdown

Bits has a CI fix ready

🟢 Investigated · 🟢 Fix prepared · ⚪ Validation skipped · 🟠 Ready

spotless failed because the new smoke-test backend sources did not match the repository Java formatter. Reformatted RemoteConfig.java, TelemetryDecoder.java, and TestAgentBackend.java without changing behavior.

Commit fix to this PR


View in Datadog | Reviewed commit 4abdba0 · Any feedback? Reach out in #deveng-pr-agent

@PerfectSlayer
PerfectSlayer force-pushed the bbujon/smoke-tests-junit-framework branch from 11530c9 to 4abdba0 Compare July 31, 2026 08:50
@PerfectSlayer

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4abdba0567

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread dd-smoke-tests/build.gradle Outdated
Comment thread dd-smoke-tests/src/main/java/datadog/smoketest/backend/TraceBackend.java Outdated
Comment thread dd-smoke-tests/src/main/java/datadog/smoketest/SmokeServerApp.java Outdated
Comment on lines +108 to +109
new PollingConditions(timeoutSeconds)
.eventually(() -> SmokeTraceAssertions.assertTraces(getTraces(), options, matchers));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject additional traces that arrive after an early match

For the default count-exact assertion, PollingConditions returns immediately when one snapshot matches. Because both backends receive traces asynchronously, the expected traces can match first and an additional trace from the same test action can arrive just afterward, causing the test to pass even though the final collection violates the exact-count contract; this also makes IGNORE_ADDITIONAL_TRACES ineffective as the distinction between strict and permissive behavior in that scenario. The strict path needs a stabilization/final-count check rather than accepting the first transient match.

Useful? React with 👍 / 👎.

Comment thread dd-smoke-tests/src/main/java/datadog/smoketest/SmokeCliApp.java Outdated
@PerfectSlayer
PerfectSlayer force-pushed the bbujon/smoke-tests-junit-framework branch 2 times, most recently from b169c19 to 9c11764 Compare July 31, 2026 12:26
@PerfectSlayer

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9c1176468d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +104 to +108
@Override
public void beforeEach(ExtensionContext context) {
if (clearsBetweenTests()) {
clear();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve startup traces for shared CLI backends

When a SmokeCliApp uses a backend that is also registered as a shared extension, the CLI process can finish and emit all of its traces during beforeAll, after which this beforeEach callback clears them before the test body runs. The CLI app's deliberate lack of an owned-backend reset cannot prevent this; TestAgentBackend only works if callers discover and enable retainAcrossTests(), while MockAgentBackend offers no retention mode, so shared CLI trace assertions are otherwise unusable.

Useful? React with 👍 / 👎.

Comment thread dd-smoke-tests/src/main/java/datadog/smoketest/AbstractSmokeApp.java Outdated
Comment thread dd-smoke-tests/src/main/java/datadog/smoketest/backend/TestAgentBackend.java Outdated
@PerfectSlayer
PerfectSlayer force-pushed the bbujon/smoke-tests-junit-framework branch from 9c11764 to b6b0809 Compare July 31, 2026 13:45
@PerfectSlayer

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b6b0809cde

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread dd-smoke-tests/src/main/java/datadog/smoketest/AbstractSmokeApp.java Outdated
Comment thread dd-smoke-tests/src/main/java/datadog/smoketest/backend/MockAgentBackend.java Outdated
@PerfectSlayer
PerfectSlayer force-pushed the bbujon/smoke-tests-junit-framework branch from b6b0809 to 20e23f3 Compare August 3, 2026 06:31
@PerfectSlayer

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 20e23f3f65

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +354 to +357
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
this.process.destroyForcibly();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Wait for forced termination after interruption

When teardown is interrupted while waiting for the child, this branch restores the interrupt flag and returns immediately after destroyForcibly(), which is asynchronous and does not guarantee the process has exited. During Gradle cancellation or another teardown interrupt, the child can therefore retain its port and files after the extension completes; the interrupted path should still confirm termination while preserving the interrupt status.

Useful? React with 👍 / 👎.

Comment on lines +66 to +69
private void collect(HandlerApi api, TraceFormat format) {
DecodedMessage message = format.decode(api.getRequest().getBody());
this.traces.addAll(message.getTraces());
api.getResponse().status(200).sendWithType(JSON, "{}");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate the submitted trace-count header

When a tracer regression sends an absent or incorrect X-Datadog-Trace-Count, the mock backend decodes and records the payload and returns 200 without checking the header, so smoke tests using this documented backend can pass despite a malformed intake request. The existing AbstractSmokeTest.handleTrace checks the decoded count against this header, and the test-agent backend enables trace_count_header by default, so the mock path should preserve the same validation rather than silently accepting the regression.

Useful? React with 👍 / 👎.

Comment thread dd-smoke-tests/src/main/java/datadog/smoketest/SmokeServerApp.java Outdated
Comment thread dd-smoke-tests/src/main/java/datadog/smoketest/backend/TestAgentBackend.java Outdated
@datadog-datadog-us1-prod

This comment has been minimized.

@PerfectSlayer
PerfectSlayer force-pushed the bbujon/smoke-tests-junit-framework branch from 20e23f3 to 76991be Compare August 3, 2026 07:50
@PerfectSlayer
PerfectSlayer marked this pull request as ready for review August 3, 2026 07:51
@PerfectSlayer
PerfectSlayer requested a review from a team as a code owner August 3, 2026 07:51

@datadog-datadog-us1-prod datadog-datadog-us1-prod Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Datadog Autotest: FAIL

The new JUnit smoke framework cannot compile as configured: the PR removes the module's direct JUnit Jupiter compile dependency while its new main sources import JUnit extension APIs. Restore that compile-only dependency before shipping. No additional tests recommended: this is a build-configuration defect, and the existing tests cannot compile until the dependency is restored.

View proposed fix
Open Bits AI session

🤖 Datadog Autotest · Commit 76991be · What is Autotest? · @DataDog review to ask questions · Any feedback? Reach out in #autotest


dependencies {
api libs.okhttp
api libs.testcontainers

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0 JUnit API dependency removed from compile classpath

The dd-smoke-tests module fails at compilation, so the new JUnit smoke framework cannot be built or consumed by smoke-test modules.

Assertion details
  • Input: Build dd-smoke-tests with the new AbstractSmokeApp, SmokeCliApp, SmokeServerApp, and backend sources present.
  • Expected: The smoke-test main source set compiles with org.junit.jupiter.api.extension available.
  • Actual: The PR removes compileOnly(libs.junit.jupiter) from dd-smoke-tests/build.gradle, while new main sources import org.junit.jupiter.api.extension.AfterAllCallback, BeforeAllCallback, BeforeEachCallback, and ExtensionContext. Gradle therefore cannot compile the new framework unless another direct/transitive dependency supplies those APIs; the module's existing project dependencies do not declare JUnit Jupiter as an API dependency.

Was this helpful? React 👍 or 👎
🤖 Datadog Autotest · What is Autotest? · @DataDog review to ask questions · Any feedback? Reach out in #autotest

Suggested change
api libs.testcontainers
api libs.testcontainers
compileOnly(libs.junit.jupiter)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What?
image

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 76991be5ec

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread dd-smoke-tests/src/main/java/datadog/smoketest/AbstractSmokeApp.java Outdated
@PerfectSlayer
PerfectSlayer force-pushed the bbujon/smoke-tests-junit-framework branch from 76991be to 0f9f704 Compare August 3, 2026 08:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp: testing Testing tag: ai generated Largely based on code generated by an AI or LLM type: feature Enhancements and improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant