ordeal — Chaos testing for Python¶
Your tests pass. Your code still breaks in production. The gap between "tests pass" and "code works" is the space of failures you never thought to test — timeouts during retries, NaN inside recovery paths, permission errors after partial writes. That space is enormous, and traditional testing doesn't cover it.
Ordeal closes this gap. You describe your system, declare what can go wrong, state what must stay true — and ordeal explores thousands of failure combinations automatically, with coverage guidance, until it either finds a violation or gives you confidence that your code handles adversity.
from ordeal import ChaosTest, rule, always
from ordeal.faults import timing, numerical
class MyServiceChaos(ChaosTest):
faults = [
timing.timeout("myapp.api.call"),
numerical.nan_injection("myapp.model.predict"),
]
@rule()
def call_service(self):
result = self.service.process("input")
always(result is not None, "process never returns None")
TestMyServiceChaos = MyServiceChaos.TestCase
When ordeal passes, it means something. Not "the tests pass" — but that the code was explored under adversity, with faults injected in combinations no human would write, and the invariants held.
Start here¶
Understand¶
Use¶
Reference¶
What ordeal brings together¶
| Capability | Idea | Origin |
|---|---|---|
| Stateful chaos testing | Nemesis toggles faults while Hypothesis explores interleavings | Jepsen + Hypothesis |
| Coverage-guided exploration | Checkpoint interesting states, branch from productive ones | Antithesis |
| Property assertions | always, sometimes, reachable, unreachable |
Antithesis |
| Inline fault injection | buggify() — no-op in production, fault in testing |
FoundationDB |
| Boundary-biased generation | Test at 0, -1, empty, max — where bugs cluster | Jane Street |
| Mutation testing | Verify tests catch real code changes | Meta ACH |