How to port tests to Antithesis

In this guide, we’ll walk through how to evolve a traditional test into an autonomous one using Antithesis, with a real-world example from Turso, a rewrite of SQLite in Rust.

Turso have open sourced their tests on github — this guide explains what they did, and shows you how to do the same for your system.

If you haven’t already done so, you might want to read the introduction and Creating test templates before tackling this.

The stress test

Turso started with a workload that stress-tests their database to ensure data integrity.

The test script:

  • Randomly generates a schema and table.
  • Generates a specified number of random SQL insert, update, and delete queries.
  • Executes the generated SQL queries.
  • Periodically checks the database for integrity violations.
ComponentCode lines
Schema and table creationgen_schema
Insert querygenerate_insert
Update querygenerate_update
Delete querygenerate_delete
Integrity checkintegritycheck

Instead of using some synthetic data and pre-written queries, this script uses randomness to lead the test. So this handwritten stress test is already stronger than a fixed example-based test, because it introduces randomized behavior, making it behave a little like real users who interact with the software in unexpected ways.

However, it still misses many potential execution paths — especially those that involve concurrency or failure scenarios.

The test also panics and exits execution when it encounters an error. While it’s good practice to exit when the system is in an unrecoverable state, it doesn’t allow you to see the consequences of encountering a bug.

Running in Antithesis

Initially, Turso simply ran the stress test binary as an entrypoint in their first Antithesis testing setup, by including a single line of code in their dockerfile. That’s all you need to do to start testing with Antithesis!

An equivalent approach, demonstrated below, is to make the stress test binary a test template. To do this, Turso made their stress test a singleton driver command by placing it in a simple shell script.

singleton_driver_stress.sh

#!/usr/bin/env bash
/bin/turso_stress --silent --nr-iterations 10000

Containerization

Whichever approach you use, Turso’s containerization setup is a helpful example of how to set up your software in Antithesis.

Test quality

Now Turso’s test is running in Antithesis’ testing environment, which means it’s running many thousands of times while being subjected to faults.

Each test run now consists of:

  • Multiple test branches experiencing different faults.
  • The software undertaking the same fixed sequence of operations on every branch.

Strengthening their testing

The next step in the evolution is to break down the monolithic stress test into one that allows Antithesis to control execution order, parallelism, and frequency, and guide the fuzzer to more interesting system states.

Here’s how the core components of the stress test map to test commands:

ComponentBecomes a Test Command
Schema and table creationfirst_setup
Insert queryparallel_driver_insert
Update queryparallel_driver_update
Delete queryparallel_driver_delete
Rollback opsparallel_driver_rollback
Integrity checkparallel_driver_integritycheck

Apart from breaking down the monolithic stress test, some of the panics in the monolith are converted into always assertions. If the assertion fails or a panic is triggered, it’ll now show up as a property failure in the triage report. This allows Turso to see what the consequences of a given error are.

Containerization

This uses the same containerization and orchestration files as above, but look for the relevant lines that refer to this directory. Note that Turso’s current testing setup for Antithesis includes both the singleton_driver_stress, and the collection of test commands.

Test quality

Each test run now consists of:

  • Multiple test branches with different sequences of events.
  • Parallel insert/update/delete/rollback operations.
The evolved test template

Here’s the triage report that this test generates. More detail on the triage report — or if you’d like to see the Logs Explorer for this test, drop us a line at support@antithesis.com.

Summary

By following this progression, you move from writing fixed examples to defining properties and behaviors, letting Antithesis explore execution paths on its own.

SetupWhat you’re testingWill you find the bug?
Example-based testing, manual runsFixed test pathOnly if it’s on the one path that you thought to test.
Example-based testing, partially randomized, manual runsTest a different path per test run, one path per clickIf randomization finds the buggy input sequence.
Example-based testing, partially randomized, automated runsTest a different path per test run, many paths per clickIf randomization finds the buggy input sequence.
Autonomous testing, singletonMany executions with randomness + fault injectionIf at least one combination of events and faults across the branches of execution leads to a bug.
Autonomous testing, full templateFully autonomous, parallel, property-based testingVery very likely!
  • Introduction
  • Welcome to Antithesis
  • How Antithesis works
  • Using Antithesis with AI
  • Get started
  • Setup guide
  • Overview
  • For Docker Compose users
  • For Kubernetes users
  • Test an example system
  • Overview
  • With Docker Compose
  • Overview
  • Build and run an etcd cluster
  • Add a test template
  • With Kubernetes
  • Overview
  • Build and run an etcd cluster
  • Add a test template
  • Product
  • Test templates
  • Overview
  • Creating test templates
  • Test commands
  • How to check a test template locally
  • How to port tests to Antithesis
  • Test launchers
  • The triage report
  • Overview
  • Findings
  • Environment
  • Utilization
  • Properties
  • Logs Explorer & multiverse map
  • Debugging
  • Overview
  • Causality analysis
  • Multiverse debugging
  • Simple Multiverse debugging
  • Advanced
  • Overview
  • The Antithesis multiverse
  • Querying with event sets
  • Environment utilities
  • Using the Antithesis Notebook
  • Cookbook
  • Tooling integrations
  • CI integration
  • Discord and Slack integrations
  • Issue tracker integration - BETA
  • Configuration
  • Access and authentication
  • The Antithesis environment
  • Best practices
  • Docker best practices
  • Kubernetes best practices
  • Optimizing for testing
  • Concepts
  • Properties and Assertions
  • Overview
  • Properties in Antithesis
  • Assertions in Antithesis
  • Sometimes Assertions
  • Properties to test for
  • Fault injection
  • Reference
  • Webhooks
  • Overview
  • Launching a test
  • Launching a debugging session
  • webhook reference
  • Antithesis API
  • Handling external dependencies
  • SDK reference
  • Overview
  • Define test properties
  • Generate randomness
  • Manage test lifecycle
  • Assertion catalog
  • Coverage instrumentation
  • Go
  • Go SDK
  • Instrumentor
  • Tutorial
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • Java
  • Java SDK
  • Using the SDK
  • Building your software
  • Tutorial
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • C SDK
  • C++
  • C++ SDK
  • C/C++ Instrumentation
  • Tutorial
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • JavaScript
  • Python
  • Python SDK
  • Tutorial
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • Rust
  • Rust SDK
  • Instrumentation
  • Tutorial
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • .NET
  • .NET SDK
  • Instrumentation
  • Tutorial
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • Languages not listed above
  • Fallback SDK
  • Assert (reference)
  • Lifecycle (reference)
  • Assertion Schema
  • FAQ
  • Product FAQs
  • About Antithesis POCs
  • Release notes
  • Release notes
  • General reliability resources
  • Reliability glossary
  • Techniques for better software testing
  • Autonomous testing
  • Deterministic simulation testing
  • Property-based testing
  • White paper — How much does an outage cost?
  • Catalog of reliability properties for key-value datastores
  • Catalog of reliability properties for blockchains
  • Test ACID compliance with a ring test