> ## Documentation Index
> Fetch the complete documentation index at: https://developers.stellar.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Differential Tests

> Differential testing detects unintended changes.

Differential testing is the testing of two things to discover differences in their behavior.

The goal is to prove that the two things behave consistently, and that they do not diverge in behavior except for some expected differences. The assertions should be as broad as possible, broadly testing that all observable outcomes do not change, except for any expected changes.

This strategy is effective when building something new that should behave like something that already exists. That could be a new version of a contract that has unchanged behavior from its previous version. Or it could be the same contract with an updated SDK or other dependency. Or it could be a refactor that expects no functional changes.

This strategy can be used in the context of unit and integration tests, or in the context of fuzz tests as well.

> [!TIP]
>
> All contracts built with the Rust Soroban SDK have a form of differential testing built-in and enabled by default. See \[Differential Testing with Test Snapshots].

## How to Write Differential Tests

To experiment with writing a differential test, open a contract that you've deployed, or checkout an example from the \[soroban-examples] repository and deploy it.

Assuming the contract has been deployed, and changes are being made to the local copy. We need to check that unchanged behavior in the contract hasn't changed compared to what is deployed.

1. Use the [stellar contract fetch] command to fetch the contract that's already deployed. The contract already deployed will be used as a baseline that the local copy is expected to behave like.

   ```shell theme={"theme":{"light":"github-light","dark":"github-dark"}}
   stellar contract fetch --id C... --out-file contract.wasm
   ```

2. Import the contract into the tests with the `contractimport!` macro.

   ```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
   mod deployed {
       soroban_sdk::contractimport!(file = "contract.wasm");
   }
   ```

3. Write a test that runs the same logic for the deployed contract and the local contract, comparing the result. Assuming the [increment example] is in use, the test would look something like the following.

   ```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
   #![cfg(test)]
   use crate::{IncrementContract, IncrementContractClient};
   use soroban_sdk::{testutils::Events as _, Env};

   mod deployed {
       soroban_sdk::contractimport!(file = "contract.wasm");
   }

   #[test]
   fn differential_test() {
       assert_eq!(
           // Baseline – the deployed contract
           {
               let env = Env::default();
               let contract_id = env.register(deployed::WASM, ());
               let client = IncrementContractClient::new(&env, &contract_id);
               (
                   // Return Values
                   (
                       client.increment(),
                       client.increment(),
                       client.increment(),
                   ),
                   // Events
                   env.events().all(),
               )
           },
           // Local – the changed or refactored contract
           {
               let env = Env::default();
               let contract_id = env.register(IncrementContract, ());
               let client = IncrementContractClient::new(&env, &contract_id);
               (
                   // Return Values
                   (
                       client.increment(),
                       client.increment(),
                       client.increment(),
                   ),
                   // Events
                   env.events().all(),
               )
           },
       );
   }
   ```

4. Run the test to compare the baseline and local observable outcomes.

This test uses the same patterns used in [unit tests] and [integration tests]:

1. Create an environment, the `Env`.
2. Import the Wasm contract to compare with.
3. Register the local contract to be tested.
4. Invoke functions using a client.
5. Assert equality.

> [!TIP]
>
> Differential tests work best when less assumptions are made. Rather than asserting only on specific return values or on implementation details like specific state, asserting on all observable outcomes and including things like events published or return values of other read-only contract functions will help to discover unexpected changes.

[Getting Started]: ../../smart-contracts/getting-started

[increment example]: https://github.com/stellar/soroban-examples/blob/main/increment/src/lib.rs

[Differential Testing with Test Snapshots]: https://developers.stellar.org/docs/build/guides/testing/differential-tests-with-test-snapshots.md

[stellar contract fetch]: https://developers.stellar.org/docs/tools/cli/stellar-cli.md#stellar-contract-fetch

[integration tests]: https://developers.stellar.org/docs/build/guides/testing/integration-tests.md

[unit tests]: https://developers.stellar.org/docs/build/guides/testing/unit-tests.md

[stellar/rs-soroban-sdk#1360]: https://github.com/stellar/rs-soroban-sdk/issues/1360
