Skip to main content

How Trace-Based Testing Works

Understanding the mechanism is essential for adopting trace-based testing. BitDive applies deterministic record and replay principles to ensure fidelity to the original execution.

Trace Recording Mechanism

Imagine your application is running in production or staging. BitDive acts as a passive observer, capturing the exact inputs, internal decisions, and external commands (like database queries) for every request.

When we create a test, we are essentially taking that captured trace and placing it into a controlled JUnit execution environment. We tell your code: "Execute this request again, exactly as you did before."

Deterministic Replay Architecture

A primary challenge in automated testing is non-determinism—tests that fail due to environmental factors like network latency, changing timestamps, or database state. BitDive addresses this through dependency virtualization.

When a BitDive test executes:

  1. Controlled Environment: Your application starts in a special "Replay Mode." This is a real Spring Boot context, but BitDive actively manages it to ensure determinism. It allows for bean overriding to disconnect real infrastructure beans (like Kafka listeners or Quartz schedulers) unless explicitly required, ensuring the test runs in isolation.

  2. Dependency Replay: When your code tries to run SELECT * FROM users, it doesn't actually connect to Postgres. The BitDive agent intercepts the call (often using standard stubbing mechanisms like Mockito under the hood), looks up the recording, and returns the exact Result Set that Postgres returned during the original capture.

    This is critical. It means your test will pass even if the real database is down, empty, or currently holds different data. The test is validated against the behavior at the time of capture.

  3. Virtual Time: If your code relies on Instant.now(), replaying it a week later could break logic that creates time-sensitive tokens. BitDive virtualizes the system clock during the test execution, ensuring that "now" is always the moment the recording happened.

Deep Call Chain Verification

Most API tests act like shallow checks—they analyze the HTTP response code to judge the system's health. If the API returns 200 OK, the test passes.

But serious bugs often hide deeper in the logic. Perhaps a performance optimization accidentally removed a critical validation step, or a refactor caused a side effect in the database that doesn't show up in the JSON response.

BitDive unit tests perform Deep Call Chain Verification:

  • Method Chain Verification: We check that Service A called Service B with the correct arguments.
  • Logic Flow: We verify that the code took the same conditional branches.
  • Data Integrity: We ensure that the objects passed between internal methods have the expected state.

If any part of this deep structure deviates from the recording, the test fails. This catches "silent failures" where the app works but the logic is fundamentally broken.

The Role of the Replay Plan

When you click "Generate Test," BitDive compiles all this capturing logic into a Replay Plan.

The Replay Plan functions as a strict execution specification. The JUnit runner reads this specification and ensures every method executes with the recorded parameters in the correct order. If any deviation occurs—such as a different argument value or an unexpected method call—the execution is halted and flagged as a regression.

This architecture calculates expectations based on stored data, reducing the need to maintain extensive custom test code. You manage the Replay Plan, which is easier to update and version control than semantic logic.