[{"data":1,"prerenderedAt":919},["ShallowReactive",2],{"page-\u002Fproperty-based-fuzz-testing-strategies\u002Fhypothesis-framework-fundamentals\u002Freproducing-failures-with-example-and-the-database\u002F":3},{"id":4,"title":5,"body":6,"description":885,"extension":886,"meta":887,"navigation":85,"path":915,"seo":916,"stem":917,"__hash__":918},"content\u002Fproperty-based-fuzz-testing-strategies\u002Fhypothesis-framework-fundamentals\u002Freproducing-failures-with-example-and-the-database\u002Findex.md","Reproducing Hypothesis Failures with @example",{"type":7,"value":8,"toc":874},"minimark",[9,22,27,50,54,63,117,120,130,163,166,176,238,356,360,369,474,478,481,487,493,522,528,532,535,546,559,563,566,645,655,661,667,671,723,799,803,809,818,831,835,864,870],[10,11,12,13,17,18,21],"p",{},"Hypothesis reports a failing input, you fix the code, and a week later the same class of bug reappears in a form nobody remembers testing. The counterexample was random, the run that found it is gone, and nothing in the repository records what was learned. Three mechanisms — the example database, ",[14,15,16],"code",{},"@example",", and ",[14,19,20],{},"@reproduce_failure"," — turn a one-off discovery into a permanent regression test, and they serve different purposes.",[23,24,26],"h2",{"id":25},"prerequisites","Prerequisites",[28,29,30,42],"ul",{},[31,32,33,37,38,41],"li",{},[34,35,36],"strong",{},"hypothesis 6.90+"," and ",[34,39,40],{},"pytest 7.0+",".",[31,43,44,45,41],{},"The settings profiles described in ",[46,47,49],"a",{"href":48},"\u002Fproperty-based-fuzz-testing-strategies\u002Fhypothesis-framework-fundamentals\u002F","hypothesis framework fundamentals",[23,51,53],{"id":52},"solution","Solution",[10,55,56,59,60,62],{},[34,57,58],{},"Pin the example."," The durable answer is an ",[14,61,16],{}," decorator carrying the shrunk input. It runs before any generated data on every execution, forever, and it is reviewable in a diff:",[64,65,70],"pre",{"className":66,"code":67,"language":68,"meta":69,"style":69},"language-python shiki shiki-themes github-light github-dark","from hypothesis import example, given, strategies as st\n\n@given(st.integers(min_value=0), st.integers(min_value=0))\n@example(0, 0)                       # the empty-basket bug, found 2026-03-14\n@example(1, 2 ** 31)                 # the overflow that reached production\ndef test_total_never_negative(price, quantity):\n    assert total(price, quantity) >= 0\n","python","",[14,71,72,80,87,93,99,105,111],{"__ignoreMap":69},[73,74,77],"span",{"class":75,"line":76},"line",1,[73,78,79],{},"from hypothesis import example, given, strategies as st\n",[73,81,83],{"class":75,"line":82},2,[73,84,86],{"emptyLinePlaceholder":85},true,"\n",[73,88,90],{"class":75,"line":89},3,[73,91,92],{},"@given(st.integers(min_value=0), st.integers(min_value=0))\n",[73,94,96],{"class":75,"line":95},4,[73,97,98],{},"@example(0, 0)                       # the empty-basket bug, found 2026-03-14\n",[73,100,102],{"class":75,"line":101},5,[73,103,104],{},"@example(1, 2 ** 31)                 # the overflow that reached production\n",[73,106,108],{"class":75,"line":107},6,[73,109,110],{},"def test_total_never_negative(price, quantity):\n",[73,112,114],{"class":75,"line":113},7,[73,115,116],{},"    assert total(price, quantity) >= 0\n",[10,118,119],{},"The comment matters as much as the values. A pinned example without provenance looks like an arbitrary case and gets deleted in a cleanup; one that names the bug it encodes survives.",[10,121,122,125,126,129],{},[34,123,124],{},"Replay while debugging."," With ",[14,127,128],{},"print_blob=True",", a failure prints a decorator that replays that exact example without regenerating anything — the fastest possible edit-run loop while fixing the code:",[64,131,133],{"className":66,"code":132,"language":68,"meta":69,"style":69},"from hypothesis import reproduce_failure\n\n@reproduce_failure(\"6.92.1\", b\"AXicY2BgYGAAAAAFAAE=\")\n@given(st.integers(), st.integers())\ndef test_total_never_negative(price, quantity):\n    ...\n",[14,134,135,140,144,149,154,158],{"__ignoreMap":69},[73,136,137],{"class":75,"line":76},[73,138,139],{},"from hypothesis import reproduce_failure\n",[73,141,142],{"class":75,"line":82},[73,143,86],{"emptyLinePlaceholder":85},[73,145,146],{"class":75,"line":89},[73,147,148],{},"@reproduce_failure(\"6.92.1\", b\"AXicY2BgYGAAAAAFAAE=\")\n",[73,150,151],{"class":75,"line":95},[73,152,153],{},"@given(st.integers(), st.integers())\n",[73,155,156],{"class":75,"line":101},[73,157,110],{},[73,159,160],{"class":75,"line":107},[73,161,162],{},"    ...\n",[10,164,165],{},"Delete it once the fix lands. The blob encodes Hypothesis's internal representation and does not survive a library upgrade, so it is a debugging aid rather than a regression test.",[10,167,168,171,172,175],{},[34,169,170],{},"Let the database do the rest."," Hypothesis writes every failing example to ",[14,173,174],{},".hypothesis\u002Fexamples\u002F"," and replays entries for that test first on the next run. Locally this is automatic; in CI it only works if the directory is cached between runs.",[64,177,181],{"className":178,"code":179,"language":180,"meta":69,"style":69},"language-yaml shiki shiki-themes github-light github-dark","- uses: actions\u002Fcache@v4\n  with:\n    path: .hypothesis\n    key: hypothesis-${{ github.ref }}-${{ github.run_id }}\n    restore-keys: hypothesis-${{ github.ref }}-\n","yaml",[14,182,183,200,208,218,228],{"__ignoreMap":69},[73,184,185,189,193,196],{"class":75,"line":76},[73,186,188],{"class":187},"sVt8B","- ",[73,190,192],{"class":191},"s9eBZ","uses",[73,194,195],{"class":187},": ",[73,197,199],{"class":198},"sZZnC","actions\u002Fcache@v4\n",[73,201,202,205],{"class":75,"line":82},[73,203,204],{"class":191},"  with",[73,206,207],{"class":187},":\n",[73,209,210,213,215],{"class":75,"line":89},[73,211,212],{"class":191},"    path",[73,214,195],{"class":187},[73,216,217],{"class":198},".hypothesis\n",[73,219,220,223,225],{"class":75,"line":95},[73,221,222],{"class":191},"    key",[73,224,195],{"class":187},[73,226,227],{"class":198},"hypothesis-${{ github.ref }}-${{ github.run_id }}\n",[73,229,230,233,235],{"class":75,"line":101},[73,231,232],{"class":191},"    restore-keys",[73,234,195],{"class":187},[73,236,237],{"class":198},"hypothesis-${{ github.ref }}-\n",[239,240,243,352],"figure",{"className":241},[242],"diagram",[244,245,252,253,252,257,252,261,252,269,252,278,252,287,252,293,252,297,252,301,252,306,252,311,252,314,252,318,252,321,252,325,252,328,252,332,252,335,252,339,252,342,252,345,252,349],"svg",{"viewBox":246,"role":247,"ariaLabelledBy":248,"xmlns":251},"0 0 760 230","img",[249,250],"reprotools-t","reprotools-d","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","\n  ",[254,255,256],"title",{"id":249},"Three mechanisms, three jobs",[258,259,260],"desc",{"id":250},"A table of the three reproduction mechanisms - the example decorator, the reproduce_failure blob and the example database - describing what each stores, how long it survives, and what it is for.",[262,263],"rect",{"x":264,"y":264,"width":265,"height":266,"rx":267,"fill":268},"0","760","230","14","#fffdf8",[270,271,256],"text",{"x":272,"y":273,"textAnchor":274,"fontSize":275,"fontWeight":276,"fill":277},"380","30","middle","15","700","#3d405b",[262,279],{"x":280,"y":281,"width":282,"height":283,"rx":284,"fill":285,"stroke":277,"strokeWidth":286},"24","52","712","40","10","#f2cc8f","1.5",[270,288,292],{"x":289,"y":290,"fontSize":291,"fontWeight":276,"fill":277},"38","76","12","Criterion",[270,294,296],{"x":295,"y":290,"textAnchor":274,"fontSize":291,"fontWeight":276,"fill":277},"390","Stores",[270,298,300],{"x":299,"y":290,"textAnchor":274,"fontSize":291,"fontWeight":276,"fill":277},"620","Survives",[262,302],{"x":280,"y":303,"width":282,"height":283,"fill":304,"stroke":277,"strokeWidth":305},"92","#f4f1de","1",[270,307,310],{"x":289,"y":308,"fontSize":309,"fill":277},"116","11.5","@example(...)",[270,312,313],{"x":295,"y":308,"textAnchor":274,"fontSize":309,"fill":277},"explicit input values",[270,315,317],{"x":299,"y":308,"textAnchor":274,"fontSize":309,"fill":316},"#2a5f49","forever, in the repo",[262,319],{"x":280,"y":320,"width":282,"height":283,"fill":268,"stroke":277,"strokeWidth":305},"132",[270,322,324],{"x":289,"y":323,"fontSize":309,"fill":277},"156","@reproduce_failure(...)",[270,326,327],{"x":295,"y":323,"textAnchor":274,"fontSize":309,"fill":277},"an encoded internal blob",[270,329,331],{"x":299,"y":323,"textAnchor":274,"fontSize":309,"fill":330},"#8f3d22","one library version",[262,333],{"x":280,"y":334,"width":282,"height":283,"fill":304,"stroke":277,"strokeWidth":305},"172",[270,336,338],{"x":289,"y":337,"fontSize":309,"fill":277},"196","the example database",[270,340,341],{"x":295,"y":337,"textAnchor":274,"fontSize":309,"fill":277},"every recent failure",[270,343,344],{"x":299,"y":337,"textAnchor":274,"fontSize":309,"fill":330},"while the cache lives",[75,346],{"x1":347,"y1":281,"x2":347,"y2":348,"stroke":277,"strokeWidth":305},"274","212",[75,350],{"x1":351,"y1":281,"x2":351,"y2":348,"stroke":277,"strokeWidth":305},"505",[353,354,355],"figcaption",{},"Only the first is a regression test; the other two are convenience layers over a search that is random by design.",[23,357,359],{"id":358},"why-this-works","Why this works",[10,361,362,363,365,366,368],{},"Hypothesis runs a test in phases: explicit examples first, then entries from the database for that test's identity, then generated data, then shrinking. ",[14,364,16],{}," inserts into the first phase, so it runs even when generation is disabled entirely. The database keys on a hash of the test's source and name, which is why renaming a test loses its history — and why the entries are pruned when the test disappears. ",[14,367,20],{}," bypasses all of it, decoding a serialized draw sequence and replaying exactly those choices, which is why it is precise and why it breaks across versions.",[239,370,372,471],{"className":371},[242],[244,373,252,378,252,381,252,384,252,401,252,403,252,405,252,411,252,417,252,422,252,428,252,431,252,435,252,438,252,442,252,445,252,449,252,452,252,456,252,459,252,463,252,466],{"viewBox":374,"role":247,"ariaLabelledBy":375,"xmlns":251},"0 0 760 172",[376,377],"hypphases-t","hypphases-d",[254,379,380],{"id":376},"The order Hypothesis runs its phases in",[258,382,383],{"id":377},"A left-to-right sequence of the phases: explicit examples from decorators, replayed entries from the example database, newly generated data, and finally shrinking of any failure found.",[385,386,387,388,252],"defs",{},"\n    ",[389,390,397],"marker",{"id":391,"viewBox":392,"refX":393,"refY":394,"markerWidth":395,"markerHeight":395,"orient":396},"hypphases-a","0 0 10 10","9","5","7","auto-start-reverse",[398,399],"path",{"d":400,"fill":285},"M0 0 L10 5 L0 10 z",[262,402],{"x":264,"y":264,"width":265,"height":334,"rx":267,"fill":268},[270,404,380],{"x":272,"y":273,"textAnchor":274,"fontSize":275,"fontWeight":276,"fill":277},[262,406],{"x":407,"y":408,"width":409,"height":290,"rx":291,"fill":304,"stroke":285,"strokeWidth":410},"26","62","142","1.8",[270,412,416],{"x":413,"y":414,"textAnchor":274,"fontSize":415,"fontWeight":276,"fill":277},"97","96","12.5","explicit",[270,418,421],{"x":413,"y":419,"textAnchor":274,"fontSize":420,"fill":277},"113","11","@example first",[75,423],{"x1":424,"y1":425,"x2":426,"y2":425,"stroke":285,"strokeWidth":410,"markerEnd":427},"176","100","208","url(#hypphases-a)",[262,429],{"x":430,"y":408,"width":409,"height":290,"rx":291,"fill":268,"stroke":285,"strokeWidth":410},"214",[270,432,434],{"x":433,"y":414,"textAnchor":274,"fontSize":415,"fontWeight":276,"fill":277},"286","reuse",[270,436,437],{"x":433,"y":419,"textAnchor":274,"fontSize":420,"fill":277},"database entries",[75,439],{"x1":440,"y1":425,"x2":441,"y2":425,"stroke":285,"strokeWidth":410,"markerEnd":427},"364","396",[262,443],{"x":444,"y":408,"width":409,"height":290,"rx":291,"fill":304,"stroke":285,"strokeWidth":410},"403",[270,446,448],{"x":447,"y":414,"textAnchor":274,"fontSize":415,"fontWeight":276,"fill":277},"474","generate",[270,450,451],{"x":447,"y":419,"textAnchor":274,"fontSize":420,"fill":277},"new random data",[75,453],{"x1":454,"y1":425,"x2":455,"y2":425,"stroke":285,"strokeWidth":410,"markerEnd":427},"552","584",[262,457],{"x":458,"y":408,"width":409,"height":290,"rx":291,"fill":268,"stroke":285,"strokeWidth":410},"592",[270,460,462],{"x":461,"y":414,"textAnchor":274,"fontSize":415,"fontWeight":276,"fill":277},"663","shrink",[270,464,465],{"x":461,"y":419,"textAnchor":274,"fontSize":420,"fill":277},"minimise a failure",[270,467,470],{"x":272,"y":468,"textAnchor":274,"fontSize":309,"fontStyle":469,"fill":277},"164","italic","phases=[Phase.explicit, Phase.reuse] gives a fast replay-only run for pre-merge checks.",[353,472,473],{},"Pinned examples always run first, which is what makes them a regression test rather than a lucky draw.",[23,475,477],{"id":476},"making-ci-runs-reproducible","Making CI runs reproducible",[10,479,480],{},"Randomness is the point of property-based testing, but a pull-request pipeline benefits from stability. Two settings give it without giving up the search.",[10,482,483,486],{},[14,484,485],{},"derandomize=True"," derives the seed from the test's identity, so the same test generates the same examples on every run. A pull request then fails or passes consistently, and a failure reproduces exactly when a colleague checks out the branch. The cost is that the pipeline stops exploring: it will never find a bug the fixed seed does not reach.",[10,488,489,490,492],{},"The usual arrangement runs both. Pull requests use a derandomised profile for stability; a scheduled job runs a randomised, high-example profile whose job is to explore, and any counterexample it finds is turned into an ",[14,491,16],{}," by the engineer who fixes it.",[64,494,496],{"className":66,"code":495,"language":68,"meta":69,"style":69},"from hypothesis import settings, Phase\n\nsettings.register_profile(\"ci\", derandomize=True, max_examples=100, print_blob=True)\nsettings.register_profile(\"nightly\", max_examples=2000, deadline=None)\nsettings.register_profile(\"replay\", phases=[Phase.explicit, Phase.reuse])\n",[14,497,498,503,507,512,517],{"__ignoreMap":69},[73,499,500],{"class":75,"line":76},[73,501,502],{},"from hypothesis import settings, Phase\n",[73,504,505],{"class":75,"line":82},[73,506,86],{"emptyLinePlaceholder":85},[73,508,509],{"class":75,"line":89},[73,510,511],{},"settings.register_profile(\"ci\", derandomize=True, max_examples=100, print_blob=True)\n",[73,513,514],{"class":75,"line":95},[73,515,516],{},"settings.register_profile(\"nightly\", max_examples=2000, deadline=None)\n",[73,518,519],{"class":75,"line":101},[73,520,521],{},"settings.register_profile(\"replay\", phases=[Phase.explicit, Phase.reuse])\n",[10,523,524,527],{},[14,525,526],{},"replay"," is worth having as a third profile: it runs only pinned examples and database entries, in seconds, which makes it a good pre-commit hook.",[23,529,531],{"id":530},"naming-and-keeping-counterexamples","Naming and keeping counterexamples",[10,533,534],{},"A pinned example is documentation, and it decays like documentation unless it is written for a reader.",[10,536,537,538,541,542,545],{},"State what the example encodes, not what the values are — ",[14,539,540],{},"# regression: quantity at INT32_MAX overflowed the total"," beats ",[14,543,544],{},"# large quantity",". Keep the example next to the property it falsifies rather than in a separate regression module, so a change to the property surfaces the example in the same diff. And when a fix makes an example structurally impossible — the parameter no longer exists — delete it deliberately rather than adapting it, because an adapted example no longer encodes the bug it was created for.",[10,547,548,549,551,552,555,556,558],{},"For teams that want the history without the decorators, ",[14,550,16],{}," accepts ",[14,553,554],{},".via(\"discovered failure\")"," metadata, and Hypothesis's ",[14,557,416],{}," phase reports which pinned examples ran. That is enough to answer \"what have we learned about this function\" during a review, which is the question an accumulated set of examples is actually answering.",[23,560,562],{"id":561},"sharing-a-database-across-a-team","Sharing a database across a team",[10,564,565],{},"The example database is per-machine by default, which means a counterexample found on CI is not replayed on a developer's laptop and vice versa. For teams that want the search to accumulate rather than restart, Hypothesis supports pluggable database backends.",[64,567,569],{"className":66,"code":568,"language":68,"meta":69,"style":69},"# conftest.py\nfrom pathlib import Path\nfrom hypothesis.database import (\n    DirectoryBasedExampleDatabase, MultiplexedDatabase, ReadOnlyDatabase,\n)\nfrom hypothesis import settings\n\nlocal = DirectoryBasedExampleDatabase(\".hypothesis\u002Fexamples\")\nshared = ReadOnlyDatabase(DirectoryBasedExampleDatabase(\"\u002Fmnt\u002Fteam-hypothesis\"))\n\nsettings.register_profile(\n    \"team\",\n    database=MultiplexedDatabase(local, shared),   # write locally, read from both\n)\n",[14,570,571,576,581,586,591,596,601,605,611,617,622,628,634,640],{"__ignoreMap":69},[73,572,573],{"class":75,"line":76},[73,574,575],{},"# conftest.py\n",[73,577,578],{"class":75,"line":82},[73,579,580],{},"from pathlib import Path\n",[73,582,583],{"class":75,"line":89},[73,584,585],{},"from hypothesis.database import (\n",[73,587,588],{"class":75,"line":95},[73,589,590],{},"    DirectoryBasedExampleDatabase, MultiplexedDatabase, ReadOnlyDatabase,\n",[73,592,593],{"class":75,"line":101},[73,594,595],{},")\n",[73,597,598],{"class":75,"line":107},[73,599,600],{},"from hypothesis import settings\n",[73,602,603],{"class":75,"line":113},[73,604,86],{"emptyLinePlaceholder":85},[73,606,608],{"class":75,"line":607},8,[73,609,610],{},"local = DirectoryBasedExampleDatabase(\".hypothesis\u002Fexamples\")\n",[73,612,614],{"class":75,"line":613},9,[73,615,616],{},"shared = ReadOnlyDatabase(DirectoryBasedExampleDatabase(\"\u002Fmnt\u002Fteam-hypothesis\"))\n",[73,618,620],{"class":75,"line":619},10,[73,621,86],{"emptyLinePlaceholder":85},[73,623,625],{"class":75,"line":624},11,[73,626,627],{},"settings.register_profile(\n",[73,629,631],{"class":75,"line":630},12,[73,632,633],{},"    \"team\",\n",[73,635,637],{"class":75,"line":636},13,[73,638,639],{},"    database=MultiplexedDatabase(local, shared),   # write locally, read from both\n",[73,641,643],{"class":75,"line":642},14,[73,644,595],{},[10,646,647,650,651,654],{},[14,648,649],{},"MultiplexedDatabase"," reads from every backend and writes to the writable ones, and wrapping the shared store in ",[14,652,653],{},"ReadOnlyDatabase"," means a developer's experiment cannot pollute it. The shared directory can be a network mount, a synced bucket, or a git repository updated by the nightly job — the interface is small enough that a custom backend is a few dozen lines.",[10,656,657,658,660],{},"Two cautions. Database entries are keyed on the test's source and name, so a refactor invalidates them silently — pinned ",[14,659,16],{}," decorators do not have this problem, which is why they remain the durable record. And the database can hold inputs derived from real data if strategies were built from production samples; treat a shared store with the same care as a cassette or a fixture file.",[10,662,663,664,666],{},"For most teams, caching the database in CI and pinning important counterexamples with ",[14,665,16],{}," is sufficient. Reach for a shared database when the search is genuinely expensive — a nightly run over thousands of examples whose findings should reach every branch immediately.",[23,668,670],{"id":669},"edge-cases-and-failure-modes","Edge cases and failure modes",[28,672,673,679,687,696,702,711],{},[31,674,675,678],{},[34,676,677],{},"Renaming a test loses its database history."," The key includes the name, so a rename starts from scratch; pinned examples are unaffected, which is another argument for them.",[31,680,681,686],{},[34,682,683,685],{},[14,684,16],{}," values are not shrunk."," They run exactly as written, so an unnecessarily large pinned example stays large in the output forever — pin the shrunk form.",[31,688,689,692,693,41],{},[34,690,691],{},"A pinned example that no longer applies fails loudly."," That is correct behaviour, and the fix is a deliberate deletion rather than a ",[14,694,695],{},"pytest.skip",[31,697,698,701],{},[34,699,700],{},"The database directory can grow."," Entries are pruned per test, but a suite with thousands of properties accumulates; a size cap on the CI cache is sufficient.",[31,703,704,710],{},[34,705,706,709],{},[14,707,708],{},"derandomize"," and the database interact."," With both active, a run replays known failures and then generates the same examples every time — reproducible, but no new coverage until the seed changes.",[31,712,713,716,717,719,720,722],{},[34,714,715],{},"Blobs are version-locked."," A ",[14,718,20],{}," left in the repository breaks the suite on the next Hypothesis upgrade, with an error that names the version mismatch.\nA note on review etiquette for pinned examples: when a pull request adds an ",[14,721,16],{},", the reviewer should be able to answer \"what bug does this encode\" from the diff alone. That means the comment matters more than the values, and a pinned example without one is worth a review comment — six months later, nobody can distinguish a hard-won counterexample from a value somebody typed while experimenting, and the indistinguishable ones get deleted during cleanups.",[239,724,726,796],{"className":725},[242],[244,727,252,732,252,735,252,738,252,741,252,743,252,747,252,751,252,755,252,760,252,763,252,765,252,769,252,772,252,776,252,778,252,781,252,784,252,787,252,789,252,793],{"viewBox":728,"role":247,"ariaLabelledBy":729,"xmlns":251},"0 0 760 320",[730,731],"exampleprovenance-t","exampleprovenance-d",[254,733,734],{"id":730},"What a pinned example should carry",[258,736,737],{"id":731},"A stack of four attributes a good pinned example has: the shrunk values, a comment naming the bug, a date or ticket reference, and placement next to the property it falsifies.",[262,739],{"x":264,"y":264,"width":265,"height":740,"rx":267,"fill":268},"320",[270,742,734],{"x":272,"y":273,"textAnchor":274,"fontSize":275,"fontWeight":276,"fill":277},[262,744],{"x":273,"y":745,"width":276,"height":281,"rx":284,"fill":304,"stroke":746,"strokeWidth":410},"56","#81b29a",[262,748],{"x":273,"y":745,"width":749,"height":281,"rx":750,"fill":746},"8","4",[270,752,754],{"x":281,"y":753,"fontSize":415,"fontWeight":276,"fill":277},"86","the shrunk values",[270,756,759],{"x":757,"y":753,"textAnchor":758,"fontSize":420,"fill":277},"714","end","the minimal form, not the original failure",[262,761],{"x":273,"y":762,"width":276,"height":281,"rx":284,"fill":268,"stroke":285,"strokeWidth":410},"120",[262,764],{"x":273,"y":762,"width":749,"height":281,"rx":750,"fill":285},[270,766,768],{"x":281,"y":767,"fontSize":415,"fontWeight":276,"fill":277},"150","a comment naming the bug",[270,770,771],{"x":757,"y":767,"textAnchor":758,"fontSize":420,"fill":277},"what it encodes, not what it contains",[262,773],{"x":273,"y":774,"width":276,"height":281,"rx":284,"fill":304,"stroke":775,"strokeWidth":410},"184","#e07a5f",[262,777],{"x":273,"y":774,"width":749,"height":281,"rx":750,"fill":775},[270,779,780],{"x":281,"y":430,"fontSize":415,"fontWeight":276,"fill":277},"a date or ticket",[270,782,783],{"x":757,"y":430,"textAnchor":758,"fontSize":420,"fill":277},"provenance survives the people",[262,785],{"x":273,"y":786,"width":276,"height":281,"rx":284,"fill":268,"stroke":277,"strokeWidth":410},"248",[262,788],{"x":273,"y":786,"width":749,"height":281,"rx":750,"fill":277},[270,790,792],{"x":281,"y":791,"fontSize":415,"fontWeight":276,"fill":277},"278","placement by the property",[270,794,795],{"x":757,"y":791,"textAnchor":758,"fontSize":420,"fill":277},"the example and its claim stay together",[353,797,798],{},"Four small conventions are the difference between an accumulating regression record and a list of magic numbers.",[23,800,802],{"id":801},"frequently-asked-questions","Frequently Asked Questions",[10,804,805,808],{},[34,806,807],{},"Why does a Hypothesis failure not reproduce on the next run?","\nBecause generation is random by default and the example database — which replays known counterexamples first — is not present. Either the directory was not cached in CI, or the failure came from a different test whose entry was pruned.",[10,810,811,814,815,817],{},[34,812,813],{},"Should I commit the .hypothesis directory?","\nNo. Cache it in CI and keep it out of version control. Pin the specific counterexamples you care about with ",[14,816,16],{},", which is explicit, reviewable and survives database loss.",[10,819,820,823,824,827,828,830],{},[34,821,822],{},"What is reproduce_failure and when should I use it?","\nIt is a decorator carrying a base64 blob that replays one exact example. Use it while fixing a bug locally and delete it afterwards, because the encoding is tied to the Hypothesis version.\n",[34,825,826],{},"Do pinned examples slow the suite down?","\nNegligibly. Each ",[14,829,16],{}," is one extra execution of the property, run before generation begins, so ten pinned examples cost ten executions against a default budget of a hundred. That is a rounding error against the value of never re-losing a counterexample.",[23,832,834],{"id":833},"related","Related",[28,836,837,843,850,857],{},[31,838,839,842],{},[46,840,841],{"href":48},"Hypothesis framework fundamentals"," — profiles, phases and the settings this builds on.",[31,844,845,849],{},[46,846,848],{"href":847},"\u002Fproperty-based-fuzz-testing-strategies\u002Fhypothesis-framework-fundamentals\u002Freducing-hypothesis-test-execution-time\u002F","Reducing Hypothesis test execution time in CI"," — why the replay profile is the cheap pre-merge option.",[31,851,852,856],{},[46,853,855],{"href":854},"\u002Fproperty-based-fuzz-testing-strategies\u002Fhypothesis-framework-fundamentals\u002Ffixing-hypothesis-flaky-health-check-failures\u002F","Fixing Hypothesis FlakyHealthCheck failures"," — the other class of non-reproducible Hypothesis failure.",[31,858,859,863],{},[46,860,862],{"href":861},"\u002Fproperty-based-fuzz-testing-strategies\u002Fadvanced-property-based-testing\u002Fwhy-hypothesis-shrinking-stalls-and-how-to-fix-it\u002F","Why Hypothesis shrinking stalls and how to fix it"," — getting a counterexample small enough to be worth pinning.",[10,865,866,867],{},"← Back to ",[46,868,869],{"href":48},"Hypothesis Framework Fundamentals",[871,872,873],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":69,"searchDepth":82,"depth":82,"links":875},[876,877,878,879,880,881,882,883,884],{"id":25,"depth":82,"text":26},{"id":52,"depth":82,"text":53},{"id":358,"depth":82,"text":359},{"id":476,"depth":82,"text":477},{"id":530,"depth":82,"text":531},{"id":561,"depth":82,"text":562},{"id":669,"depth":82,"text":670},{"id":801,"depth":82,"text":802},{"id":833,"depth":82,"text":834},"Reproduce a Hypothesis counterexample reliably: the example database, @example pins, @reproduce_failure blobs, derandomize, and what to cache in CI.","md",{"slug":888,"type":889,"breadcrumb":890,"datePublished":891,"dateModified":891,"faq":892,"howto":899},"reproducing-failures-with-example-and-the-database","article","Reproducing Failures","2026-08-01",[893,895,897],{"q":807,"a":894},"Because generation is random by default and the example database — which replays known counterexamples first — is not present. Either the directory was not cached in CI, or the failure came from a different test whose entry was pruned.",{"q":813,"a":896},"No. Cache it in CI and keep it out of version control. Pin the specific counterexamples you care about with @example, which is explicit, reviewable and survives database loss.",{"q":822,"a":898},"It is a decorator carrying a base64 blob that replays one exact example. Use it while fixing a bug locally and delete it afterwards, because the encoding is tied to the Hypothesis version.",{"name":900,"description":901,"steps":902},"How to reproduce a Hypothesis failure","Turn a random counterexample into a deterministic, permanent regression test.",[903,906,909,912],{"name":904,"text":905},"Copy the falsifying example from the output","The report prints the shrunk arguments that failed.",{"name":907,"text":908},"Pin it with an example decorator","Add the values as an explicit example so they run on every future execution.",{"name":910,"text":911},"Use reproduce_failure for the debugging loop","Paste the printed blob to replay that exact example while fixing the code.",{"name":913,"text":914},"Cache the example database in CI","Persist the directory between runs so known counterexamples are replayed automatically.","\u002Fproperty-based-fuzz-testing-strategies\u002Fhypothesis-framework-fundamentals\u002Freproducing-failures-with-example-and-the-database",{"title":5,"description":885},"property-based-fuzz-testing-strategies\u002Fhypothesis-framework-fundamentals\u002Freproducing-failures-with-example-and-the-database\u002Findex","7wKEG6GNmT2B8_gpInDla519UwkmYLycXzQGD8-aOrY",1785613404363]