[{"data":1,"prerenderedAt":859},["ShallowReactive",2],{"page-\u002Fproperty-based-fuzz-testing-strategies\u002Fhypothesis-integration-with-pytest-and-frameworks\u002Frunning-hypothesis-under-pytest-xdist\u002F":3},{"id":4,"title":5,"body":6,"description":822,"extension":823,"meta":824,"navigation":83,"path":855,"seo":856,"stem":857,"__hash__":858},"content\u002Fproperty-based-fuzz-testing-strategies\u002Fhypothesis-integration-with-pytest-and-frameworks\u002Frunning-hypothesis-under-pytest-xdist\u002Findex.md","Running Hypothesis Under pytest-xdist",{"type":7,"value":8,"toc":811},"minimark",[9,18,21,26,51,55,167,231,399,403,410,425,429,472,476,479,490,496,502,576,580,586,593,612,618,687,691,709,719,727,737,741,747,759,769,773,802,807],[10,11,12,13,17],"p",{},"Property tests are some of the slowest in a suite, which makes them natural candidates for ",[14,15,16],"code",{},"pytest-xdist",". The combination mostly just works — Hypothesis tests are independent test items like any others, and xdist distributes them across workers — but three details change under parallelism. The on-disk example database is shared by default, deadlines measured in wall-clock time become noisy when workers compete for CPU, and reproducing a failure requires knowing that the worker it happened on does not matter.",[10,19,20],{},"Handling those three details is a few lines of configuration. The result is property tests that run at the speed of the parallel suite, with failures that are as easy to reproduce as in a serial run.",[22,23,25],"h2",{"id":24},"prerequisites","Prerequisites",[27,28,29,43],"ul",{},[30,31,32,35,36,35,39,42],"li",{},[14,33,34],{},"hypothesis >= 6.100",", ",[14,37,38],{},"pytest-xdist >= 3.5",[14,40,41],{},"pytest >= 8.0",".",[30,44,45,46,42],{},"Settings profiles as in ",[47,48,50],"a",{"href":49},"\u002Fproperty-based-fuzz-testing-strategies\u002Fhypothesis-integration-with-pytest-and-frameworks\u002F","Hypothesis integration with pytest and frameworks",[22,52,54],{"id":53},"solution","Solution",[56,57,62],"pre",{"className":58,"code":59,"language":60,"meta":61,"style":61},"language-python shiki shiki-themes github-light github-dark","# conftest.py\nimport os\n\nfrom hypothesis import settings\nfrom hypothesis.database import DirectoryBasedExampleDatabase\n\nworker = os.environ.get(\"PYTEST_XDIST_WORKER\", \"master\")\n\nsettings.register_profile(\n    \"ci\",\n    max_examples=300,\n    deadline=None,                      # contention, not code, dominates timing here\n    print_blob=True,                    # every failure prints @reproduce_failure(...)\n    database=DirectoryBasedExampleDatabase(f\".hypothesis\u002Fexamples\u002F{worker}\"),\n)\nsettings.register_profile(\"dev\", max_examples=30)\nsettings.load_profile(os.environ.get(\"HYPOTHESIS_PROFILE\", \"dev\"))\n","python","",[14,63,64,72,78,85,91,97,102,108,113,119,125,131,137,143,149,155,161],{"__ignoreMap":61},[65,66,69],"span",{"class":67,"line":68},"line",1,[65,70,71],{},"# conftest.py\n",[65,73,75],{"class":67,"line":74},2,[65,76,77],{},"import os\n",[65,79,81],{"class":67,"line":80},3,[65,82,84],{"emptyLinePlaceholder":83},true,"\n",[65,86,88],{"class":67,"line":87},4,[65,89,90],{},"from hypothesis import settings\n",[65,92,94],{"class":67,"line":93},5,[65,95,96],{},"from hypothesis.database import DirectoryBasedExampleDatabase\n",[65,98,100],{"class":67,"line":99},6,[65,101,84],{"emptyLinePlaceholder":83},[65,103,105],{"class":67,"line":104},7,[65,106,107],{},"worker = os.environ.get(\"PYTEST_XDIST_WORKER\", \"master\")\n",[65,109,111],{"class":67,"line":110},8,[65,112,84],{"emptyLinePlaceholder":83},[65,114,116],{"class":67,"line":115},9,[65,117,118],{},"settings.register_profile(\n",[65,120,122],{"class":67,"line":121},10,[65,123,124],{},"    \"ci\",\n",[65,126,128],{"class":67,"line":127},11,[65,129,130],{},"    max_examples=300,\n",[65,132,134],{"class":67,"line":133},12,[65,135,136],{},"    deadline=None,                      # contention, not code, dominates timing here\n",[65,138,140],{"class":67,"line":139},13,[65,141,142],{},"    print_blob=True,                    # every failure prints @reproduce_failure(...)\n",[65,144,146],{"class":67,"line":145},14,[65,147,148],{},"    database=DirectoryBasedExampleDatabase(f\".hypothesis\u002Fexamples\u002F{worker}\"),\n",[65,150,152],{"class":67,"line":151},15,[65,153,154],{},")\n",[65,156,158],{"class":67,"line":157},16,[65,159,160],{},"settings.register_profile(\"dev\", max_examples=30)\n",[65,162,164],{"class":67,"line":163},17,[65,165,166],{},"settings.load_profile(os.environ.get(\"HYPOTHESIS_PROFILE\", \"dev\"))\n",[56,168,172],{"className":169,"code":170,"language":171,"meta":61,"style":61},"language-bash shiki shiki-themes github-light github-dark","# CI: parallel, with the CI profile.\nHYPOTHESIS_PROFILE=ci pytest -n auto -q\n\n# Locally: reproduce a failure reported from worker gw5, serially.\npytest tests\u002Ftest_parser.py::test_round_trip -q    # after pasting @reproduce_failure\n","bash",[14,173,174,180,208,212,217],{"__ignoreMap":61},[65,175,176],{"class":67,"line":68},[65,177,179],{"class":178},"sJ8bj","# CI: parallel, with the CI profile.\n",[65,181,182,186,190,194,198,202,205],{"class":67,"line":74},[65,183,185],{"class":184},"sVt8B","HYPOTHESIS_PROFILE",[65,187,189],{"class":188},"szBVR","=",[65,191,193],{"class":192},"sZZnC","ci",[65,195,197],{"class":196},"sScJk"," pytest",[65,199,201],{"class":200},"sj4cs"," -n",[65,203,204],{"class":192}," auto",[65,206,207],{"class":200}," -q\n",[65,209,210],{"class":67,"line":80},[65,211,84],{"emptyLinePlaceholder":83},[65,213,214],{"class":67,"line":87},[65,215,216],{"class":178},"# Locally: reproduce a failure reported from worker gw5, serially.\n",[65,218,219,222,225,228],{"class":67,"line":93},[65,220,221],{"class":196},"pytest",[65,223,224],{"class":192}," tests\u002Ftest_parser.py::test_round_trip",[65,226,227],{"class":200}," -q",[65,229,230],{"class":178},"    # after pasting @reproduce_failure\n",[232,233,236,395],"figure",{"className":234},[235],"diagram",[237,238,245,246,245,250,245,254,245,272,245,280,245,290,245,298,245,304,245,307,245,311,245,314,245,318,245,321,245,325,245,332,245,335,245,338,245,341,245,348,245,354,245,359,245,363,245,367,245,371,245,376,245,383,245,387,245,391],"svg",{"viewBox":239,"role":240,"ariaLabelledBy":241,"xmlns":244},"0 0 820 262","img",[242,243],"hx-t","hx-d","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","\n  ",[247,248,249],"title",{"id":242},"Per-worker example databases under xdist",[251,252,253],"desc",{"id":243},"Four xdist workers each run a share of the property tests. Each writes failing examples to its own directory under the Hypothesis database path, so no two workers write to the same place. A failure prints a reproduction blob that can be replayed serially without knowing which worker produced it.",[255,256,257,258,245],"defs",{},"\n    ",[259,260,267],"marker",{"id":261,"viewBox":262,"refX":263,"refY":264,"markerWidth":265,"markerHeight":265,"orient":266},"hx-a","0 0 10 10","9","5","7","auto-start-reverse",[268,269],"path",{"d":270,"fill":271},"M0 0 L10 5 L0 10 z","#81b29a",[273,274],"rect",{"x":275,"y":275,"width":276,"height":277,"rx":278,"fill":279},"0","820","262","14","#fffdf8",[281,282,289],"text",{"x":283,"y":284,"textAnchor":285,"fontSize":286,"fontWeight":287,"fill":288},"410","28","middle","16","700","#3d405b","Separate databases, portable reproductions",[273,291],{"x":292,"y":293,"width":294,"height":295,"rx":263,"fill":296,"stroke":288,"strokeWidth":297},"26","52","160","40","#f4f1de","1.5",[281,299,303],{"x":300,"y":301,"textAnchor":285,"fontSize":302,"fill":288},"106","77","11.5","worker gw0",[273,305],{"x":292,"y":306,"width":294,"height":295,"rx":263,"fill":296,"stroke":288,"strokeWidth":297},"102",[281,308,310],{"x":300,"y":309,"textAnchor":285,"fontSize":302,"fill":288},"127","worker gw1",[273,312],{"x":292,"y":313,"width":294,"height":295,"rx":263,"fill":296,"stroke":288,"strokeWidth":297},"152",[281,315,317],{"x":300,"y":316,"textAnchor":285,"fontSize":302,"fill":288},"177","worker gw2",[273,319],{"x":292,"y":320,"width":294,"height":295,"rx":263,"fill":296,"stroke":288,"strokeWidth":297},"202",[281,322,324],{"x":300,"y":323,"textAnchor":285,"fontSize":302,"fill":288},"227","worker gw3",[67,326],{"x1":327,"y1":328,"x2":329,"y2":328,"stroke":271,"strokeWidth":330,"markerEnd":331},"190","72","300","1.6","url(#hx-a)",[67,333],{"x1":327,"y1":334,"x2":329,"y2":334,"stroke":271,"strokeWidth":330,"markerEnd":331},"122",[67,336],{"x1":327,"y1":337,"x2":329,"y2":337,"stroke":271,"strokeWidth":330,"markerEnd":331},"172",[67,339],{"x1":327,"y1":340,"x2":329,"y2":340,"stroke":271,"strokeWidth":330,"markerEnd":331},"222",[273,342],{"x":343,"y":293,"width":344,"height":327,"rx":345,"fill":346,"stroke":271,"strokeWidth":347},"306","230","11","#e6f0ea","2",[281,349,353],{"x":350,"y":351,"textAnchor":285,"fontSize":352,"fontWeight":287,"fill":288},"421","78","12",".hypothesis\u002Fexamples\u002F",[281,355,358],{"x":356,"y":357,"fontSize":345,"fill":288},"330","110","gw0\u002F",[281,360,362],{"x":356,"y":361,"fontSize":345,"fill":288},"140","gw1\u002F",[281,364,366],{"x":356,"y":365,"fontSize":345,"fill":288},"170","gw2\u002F",[281,368,370],{"x":356,"y":369,"fontSize":345,"fill":288},"200","gw3\u002F",[281,372,375],{"x":350,"y":373,"textAnchor":285,"fontSize":345,"fill":374},"228","#2a5f49","no shared writes",[273,377],{"x":378,"y":379,"width":373,"height":380,"rx":345,"fill":381,"stroke":382,"strokeWidth":347},"566","96","100","#f7f0da","#f2cc8f",[281,384,386],{"x":385,"y":334,"textAnchor":285,"fontSize":352,"fontWeight":287,"fill":288},"680","failure output",[281,388,390],{"x":385,"y":389,"textAnchor":285,"fontSize":345,"fill":288},"146","@reproduce_failure(…)",[281,392,394],{"x":385,"y":365,"textAnchor":285,"fontSize":345,"fill":393},"#8a5a00","replays on any machine",[396,397,398],"figcaption",{},"The blob, not the worker's database, is what makes a CI failure reproducible locally; the per-worker directories simply stop workers interfering.",[22,400,402],{"id":401},"why-this-works","Why this works",[10,404,405,406,409],{},"Each xdist worker is a separate process that loads the configuration independently, so reading ",[14,407,408],{},"PYTEST_XDIST_WORKER"," when registering the profile gives every worker its own database directory. The workers then never write to the same place, which removes the rare but confusing races where one worker deletes an entry another is replaying.",[10,411,412,413,416,417,420,421,424],{},"Reproduction does not depend on the worker because Hypothesis's generation is a function of the test and its seed, not of the process that ran it. ",[14,414,415],{},"print_blob=True"," makes each failure print a ",[14,418,419],{},"@reproduce_failure"," decorator encoding the exact choices that produced the failing example; pasting it onto the test and running without ",[14,422,423],{},"-n"," replays that example deterministically on any machine.",[22,426,428],{"id":427},"edge-cases-and-failure-modes","Edge cases and failure modes",[27,430,431,438,448,457,463],{},[30,432,433,437],{},[434,435,436],"strong",{},"Deadlines under contention."," Eight workers on four cores slow every example, and a deadline tuned on an idle laptop fires spuriously. Disable or widen it in the parallel profile.",[30,439,440,443,444,447],{},[434,441,442],{},"Budgets multiplied unintentionally."," ",[14,445,446],{},"max_examples"," is per test, not per run, so parallelism does not reduce the number of examples — it only spreads them. Keep the CI budget what CI can afford serially divided by the worker count.",[30,449,450,443,453,456],{},[434,451,452],{},"Health checks tripping on slow generation.",[14,454,455],{},"HealthCheck.too_slow"," measures generation time, which also suffers under contention. Suppress it only in the CI profile if it fires spuriously there.",[30,458,459,462],{},[434,460,461],{},"Stale per-worker databases."," Cached across CI runs, a worker's database can replay an example from a different code version. Clear them when caching, or disable the database in CI.",[30,464,465,468,469,471],{},[434,466,467],{},"Blob versions."," A ",[14,470,419],{}," blob is tied to the Hypothesis version that printed it. Reproduce with the same version, pinned in the lockfile.",[22,473,475],{"id":474},"choosing-whether-to-keep-the-database-in-ci","Choosing whether to keep the database in CI",[10,477,478],{},"The per-worker database is one of two reasonable CI strategies, and the other — no database at all — is often simpler.",[10,480,481,482,485,486,489],{},"With ",[14,483,484],{},"database=None"," in the CI profile, every CI run is a fresh search. Nothing is replayed, so nothing stale can be replayed, and there are no directories to cache, isolate or clean. Failures are reproduced through the printed blob, and any failure worth keeping becomes an explicit ",[14,487,488],{},"@example"," in the test file, where it runs on every future execution and is visible in code review.",[10,491,492,493,495],{},"Keeping per-worker databases, and caching them between runs, adds replay: a failure found on Monday is retried first on Tuesday, even if the random search would not have found it again. That is valuable for long-running nightly searches, where a hard-won counterexample should not be lost. It is less valuable on pull requests, where the pinned ",[14,494,488],{}," approach gives the same durability with less machinery.",[10,497,498,499,501],{},"A common split is ",[14,500,484],{}," for pull-request runs and per-worker databases, persisted as artefacts, for the nightly deep search. The pull-request suite stays simple and deterministic in its inputs; the nightly search accumulates counterexamples and promotes the important ones to explicit examples.",[232,503,505,573],{"className":504},[235],[237,506,245,511,245,514,245,517,245,521,245,526,245,531,245,537,245,541,245,545,245,549,245,553,245,556,245,560,245,564,245,567,245,570],{"viewBox":507,"role":240,"ariaLabelledBy":508,"xmlns":244},"0 0 800 236",[509,510],"dbc-t","dbc-d",[247,512,513],{"id":509},"Database strategy per pipeline stage",[251,515,516],{"id":510},"Pull-request runs use no example database, relying on printed blobs for reproduction and explicit example decorators for regressions. Nightly deep searches keep per-worker databases persisted as artefacts so hard-won counterexamples are replayed and can be promoted to explicit examples.",[273,518],{"x":275,"y":275,"width":519,"height":520,"rx":278,"fill":279},"800","236",[281,522,525],{"x":523,"y":284,"textAnchor":285,"fontSize":524,"fontWeight":287,"fill":288},"400","15.5","Simple on pull requests, persistent at night",[273,527],{"x":292,"y":528,"width":529,"height":530,"rx":352,"fill":346,"stroke":271,"strokeWidth":347},"50","360","164",[281,532,536],{"x":533,"y":534,"textAnchor":285,"fontSize":535,"fontWeight":287,"fill":288},"206","76","12.5","pull requests",[281,538,484],{"x":539,"y":540,"fontSize":345,"fill":288},"44","104",[281,542,544],{"x":539,"y":543,"fontSize":345,"fill":288},"126","fresh search every run",[281,546,548],{"x":539,"y":547,"fontSize":345,"fill":288},"148","blob for reproduction",[281,550,552],{"x":539,"y":551,"fontSize":345,"fontWeight":287,"fill":374},"186","regressions pinned with @example",[273,554],{"x":555,"y":528,"width":529,"height":530,"rx":352,"fill":381,"stroke":382,"strokeWidth":347},"414",[281,557,559],{"x":558,"y":534,"textAnchor":285,"fontSize":535,"fontWeight":287,"fill":288},"594","nightly deep search",[281,561,563],{"x":562,"y":540,"fontSize":345,"fill":288},"432","per-worker databases",[281,565,566],{"x":562,"y":543,"fontSize":345,"fill":288},"persisted as artefacts",[281,568,569],{"x":562,"y":547,"fontSize":345,"fill":288},"large max_examples",[281,571,572],{"x":562,"y":551,"fontSize":345,"fontWeight":287,"fill":393},"promote finds to @example",[396,574,575],{},"Either stage alone works; together they give fast deterministic pull-request runs and a search that keeps what it finds.",[22,577,579],{"id":578},"sizing-the-budget-for-a-parallel-run","Sizing the budget for a parallel run",[10,581,582,583,585],{},"Parallelism changes how long the suite takes, not how much work it does. Every property test still runs ",[14,584,446],{}," examples; xdist only decides which worker runs them. That has two consequences worth planning for.",[10,587,588,589,592],{},"First, the wall-clock time of the property tests is bounded below by the slowest single test. If one stateful machine takes ninety seconds at the CI budget, no number of workers makes the suite finish faster than ninety seconds, because a single test is never split across workers. When the property tests dominate the run, look at the distribution of per-test durations with ",[14,590,591],{},"--durations=20"," before adding workers: a long tail of one or two expensive tests is fixed by lowering their individual budgets or moving them to the nightly profile, not by more parallelism.",[10,594,595,596,599,600,603,604,607,608,611],{},"Second, the load balancing only works if the scheduler can see the work. The default ",[14,597,598],{},"--dist load"," sends tests to idle workers in small batches, which copes well with uneven test durations. ",[14,601,602],{},"--dist loadfile"," and ",[14,605,606],{},"--dist loadscope"," group tests by module or class, which is useful when module-scoped fixtures are expensive, but it means one module full of heavy property tests lands on a single worker while the others idle. If the property tests live together in one file, prefer ",[14,609,610],{},"load",", or split the file.",[10,613,614,615,617],{},"A practical sequence is to set the CI budget first — what gives acceptable confidence per test — then measure the serial runtime of the property tests, then choose a worker count that brings the total inside the pipeline's time limit. Picking the worker count first and then raising ",[14,616,446],{}," \"because there is spare capacity\" tends to produce a suite that is fast on the CI runner and painfully slow on a developer laptop running the same profile.",[232,619,621,684],{"className":620},[235],[237,622,245,627,245,630,245,633,245,636,245,639,245,643,245,649,245,652,245,654,245,657,245,661,245,664,245,669,245,675,245,681],{"viewBox":623,"role":240,"ariaLabelledBy":624,"xmlns":244},"0 0 800 232",[625,626],"hxb-t","hxb-d",[247,628,629],{"id":625},"The slowest single test bounds parallel runtime",[251,631,632],{"id":626},"Four worker lanes are shown as horizontal bars. Three lanes finish early with many short property tests, while one lane is occupied by a single long stateful test. The run ends when that long test ends, so adding workers does not shorten it.",[273,634],{"x":275,"y":275,"width":519,"height":635,"rx":278,"fill":279},"232",[281,637,638],{"x":523,"y":284,"textAnchor":285,"fontSize":524,"fontWeight":287,"fill":288},"One long test sets the finish line",[281,640,642],{"x":641,"y":328,"fontSize":345,"fill":288},"30","gw0",[273,644],{"x":645,"y":646,"width":329,"height":647,"rx":264,"fill":346,"stroke":271,"strokeWidth":648},"70","58","22","1.4",[281,650,651],{"x":641,"y":357,"fontSize":345,"fill":288},"gw1",[273,653],{"x":645,"y":379,"width":356,"height":647,"rx":264,"fill":346,"stroke":271,"strokeWidth":648},[281,655,656],{"x":641,"y":547,"fontSize":345,"fill":288},"gw2",[273,658],{"x":645,"y":659,"width":660,"height":647,"rx":264,"fill":346,"stroke":271,"strokeWidth":648},"134","280",[281,662,663],{"x":641,"y":551,"fontSize":345,"fill":288},"gw3",[273,665],{"x":645,"y":337,"width":666,"height":647,"rx":264,"fill":667,"stroke":668,"strokeWidth":330},"620","#fbe9e3","#e07a5f",[281,670,674],{"x":671,"y":672,"textAnchor":285,"fontSize":345,"fill":673},"380","187","#8f3d22","one stateful machine at full budget",[67,676],{"x1":287,"y1":677,"x2":287,"y2":533,"stroke":678,"strokeWidth":648,"strokeDashArray":679},"48","rgba(61,64,91,0.4)",[264,680],"4",[281,682,683],{"x":287,"y":340,"textAnchor":285,"fontSize":345,"fill":288},"run ends",[396,685,686],{},"Before adding workers, check whether one expensive property test is holding the run open; lowering its budget is the cheaper fix.",[22,688,690],{"id":689},"walking-through-a-worker-failure","Walking through a worker failure",[10,692,693,694,697,698,701,702,704,705,708],{},"A typical report from a parallel run looks like this: worker ",[14,695,696],{},"gw5"," fails ",[14,699,700],{},"test_round_trip"," with a falsifying example and, because ",[14,703,415],{}," is set, a line beginning ",[14,706,707],{},"@reproduce_failure('6.112.0', b'AXic...')",". The rest of the suite passes.",[10,710,711,712,715,716,718],{},"The first move is to ignore the worker name. It records where the test happened to be scheduled, which depends on timing and on how many workers were available, and it has no influence on the generated data. Copy the decorator, add it above ",[14,713,714],{},"@given"," on the failing test, and run that single test node without ",[14,717,423],{},". The failure reproduces immediately and deterministically, with the same shrunk example, in a debugger if needed.",[10,720,721,722,726],{},"If the failure does ",[723,724,725],"em",{},"not"," reproduce serially, the cause is almost never Hypothesis. It is the usual xdist suspects: state shared through a module-level global that another test on the same worker mutated, a temporary file path that two workers both used, or a fixture whose scope leaked data between tests. In that case the blob still helps, because it removes the input as a variable — the example is fixed, so any remaining difference is in the environment. Run the failing test alongside the other tests that shared its worker, using the collection order xdist logged, to find the interfering neighbour.",[10,728,729,730,732,733,736],{},"Once the cause is fixed, remove the ",[14,731,419],{}," decorator — it is a debugging aid tied to one Hypothesis version — and keep the example permanently with ",[14,734,735],{},"@example(...)",", which survives upgrades and documents the case for readers of the test.",[22,738,740],{"id":739},"frequently-asked-questions","Frequently Asked Questions",[10,742,743,746],{},[434,744,745],{},"Is the Hypothesis example database safe with parallel workers?","\nThe default directory-based database tolerates concurrent access in the common case, but several workers writing and deleting entries in one directory can race and produce confusing replays. Giving each worker its own directory, or disabling the database in CI, removes the problem entirely.",[10,748,749,752,753,755,756,758],{},[434,750,751],{},"How do I reproduce a failure that happened on one xdist worker?","\nUse the ",[14,754,419],{}," decorator Hypothesis prints, or the printed seed, and run just that test without ",[14,757,423],{},". Hypothesis's generation does not depend on which worker ran the test, so the failure reproduces serially.",[10,760,761,764,765,768],{},[434,762,763],{},"Why do Hypothesis deadlines fail more often under xdist?","\nBecause workers compete for CPU, so individual examples take longer than on an idle machine. A deadline tuned serially can be exceeded by a healthy example. Raise it, or set ",[14,766,767],{},"deadline=None"," for tests whose timing is not the point.",[22,770,772],{"id":771},"related","Related",[27,774,775,781,788,795],{},[30,776,777,780],{},[47,778,779],{"href":49},"Hypothesis Integration with pytest & Frameworks"," — profiles and the example database.",[30,782,783,787],{},[47,784,786],{"href":785},"\u002Fadvanced-pytest-architecture-configuration\u002Foptimizing-test-discovery\u002Fpytest-xdist-vs-pytest-parallel-performance-comparison\u002F","pytest-xdist vs pytest-parallel Performance"," — how xdist distributes work.",[30,789,790,794],{},[47,791,793],{"href":792},"\u002Fproperty-based-fuzz-testing-strategies\u002Fhypothesis-framework-fundamentals\u002Freproducing-failures-with-example-and-the-database\u002F","Reproducing Failures with @example and the Database"," — pinning what a search finds.",[30,796,797,801],{},[47,798,800],{"href":799},"\u002Fproperty-based-fuzz-testing-strategies\u002Fhypothesis-framework-fundamentals\u002Fchoosing-max-examples-and-deadline-settings\u002F","Choosing max_examples and deadline Settings"," — budgets for serial and parallel runs.",[10,803,804,805],{},"← Back to ",[47,806,779],{"href":49},[808,809,810],"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 .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":61,"searchDepth":74,"depth":74,"links":812},[813,814,815,816,817,818,819,820,821],{"id":24,"depth":74,"text":25},{"id":53,"depth":74,"text":54},{"id":401,"depth":74,"text":402},{"id":427,"depth":74,"text":428},{"id":474,"depth":74,"text":475},{"id":578,"depth":74,"text":579},{"id":689,"depth":74,"text":690},{"id":739,"depth":74,"text":740},{"id":771,"depth":74,"text":772},"Run property tests in parallel safely: per-worker example databases, deterministic seeds, reproducing a worker's failure, budget scaling and deadline noise under load.","md",{"slug":825,"type":826,"breadcrumb":827,"datePublished":828,"dateModified":828,"faq":829,"howto":836},"running-hypothesis-under-pytest-xdist","article","Hypothesis + xdist","2026-09-18",[830,832,834],{"q":745,"a":831},"The default directory-based database tolerates concurrent access in the common case, but several workers writing and deleting entries in one directory can race and produce confusing replays. Giving each worker its own directory, or disabling the database in CI, removes the problem entirely.",{"q":751,"a":833},"Use the @reproduce_failure decorator Hypothesis prints, or the printed seed, and run just that test without -n. Hypothesis's generation does not depend on which worker ran the test, so the failure reproduces serially.",{"q":763,"a":835},"Because workers compete for CPU, so individual examples take longer than on an idle machine. A deadline tuned serially can be exceeded by a healthy example. Raise it, or set deadline=None for tests whose timing is not the point.",{"name":837,"description":838,"steps":839},"How to run Hypothesis tests under pytest-xdist","Isolate the example database per worker, print reproducible failures, scale budgets to the parallel run, and relax deadlines that measure contention.",[840,843,846,849,852],{"name":841,"text":842},"Give each worker its own database","Set the example database directory from PYTEST_XDIST_WORKER in a settings profile.",{"name":844,"text":845},"Print reproduction blobs","Enable print_blob so any failure includes a decorator that reproduces it serially.",{"name":847,"text":848},"Reproduce serially","Run the failing test alone without -n using the printed blob or seed.",{"name":850,"text":851},"Relax deadlines for contended runs","Raise or disable per-example deadlines in the CI profile used with xdist.",{"name":853,"text":854},"Persist databases as artefacts","Upload the per-worker database directories from failed CI runs for local replay.","\u002Fproperty-based-fuzz-testing-strategies\u002Fhypothesis-integration-with-pytest-and-frameworks\u002Frunning-hypothesis-under-pytest-xdist",{"title":5,"description":822},"property-based-fuzz-testing-strategies\u002Fhypothesis-integration-with-pytest-and-frameworks\u002Frunning-hypothesis-under-pytest-xdist\u002Findex","jmblHk0cINea9fbJHu_6XQtKbGA48roprT3lp7kWxaA",1789718768972]