2424# ./scripts/run_integration_tests.sh
2525# ./scripts/run_integration_tests.sh --with-perf # also run the perf test
2626#
27+ # Buckets (--bucket=<name>): the slowest tests are split into their own buckets
28+ # so they can run as separate parallel CI jobs and are skipped by default
29+ # locally. Each slow bucket is path-scoped so it only imports its own module.
30+ # core (default) everything except the slow buckets below
31+ # long-sync sync lease-extension tests (test_lease_extension.py, ~90s)
32+ # long-async async lease-extension tests (test_async_lease_extension.py, ~90s)
33+ # test-all aggregate workflow-client test_all (test_workflow_client_intg.py, ~83s)
34+ # all the full suite (no bucket filtering) — for a complete local run
35+ #
36+ # ./scripts/run_integration_tests.sh # fast: skips slow buckets
37+ # ./scripts/run_integration_tests.sh --bucket=long-sync
38+ # ./scripts/run_integration_tests.sh --bucket=all # run everything
39+ #
2740# Any other arguments are passed straight through to pytest, which is handy for
2841# targeting a subset of tests or getting more detail on failures:
2942#
@@ -48,22 +61,66 @@ set -euo pipefail
4861REPO_ROOT=" $( cd " $( dirname " ${BASH_SOURCE[0]} " ) /.." && pwd) "
4962cd " $REPO_ROOT "
5063
64+ # Slow-test files that get their own buckets / CI jobs (see --bucket above).
65+ LEASE_SYNC=tests/integration/test_lease_extension.py
66+ LEASE_ASYNC=tests/integration/test_async_lease_extension.py
67+ TEST_ALL_FILE=tests/integration/test_workflow_client_intg.py
68+
5169# The perf test is skipped by default; --with-perf opts back in.
5270perf_ignore=(--ignore=tests/integration/test_update_task_v2_perf.py)
71+ bucket=" core"
5372pytest_args=()
5473for arg in " $@ " ; do
55- if [[ " $arg " == " --with-perf " ]] ; then
56- perf_ignore=()
57- else
58- pytest_args+=(" $arg " )
59- fi
74+ case " $arg " in
75+ --with-perf) perf_ignore=() ;;
76+ --bucket= * ) bucket= " ${arg #* =} " ;;
77+ * ) pytest_args+=(" $arg " ) ;;
78+ esac
6079done
6180
81+ # The AI/agentic tests always target a dedicated server (see header) and are
82+ # never part of these buckets.
83+ ai_ignore=(
84+ --ignore=tests/integration/test_ai_task_types.py
85+ --ignore=tests/integration/test_ai_examples.py
86+ --ignore=tests/integration/test_agentic_workflows.py
87+ )
88+
89+ # Build the target paths + selection for the chosen bucket. The slow buckets are
90+ # path-scoped so each job only imports its own module: this keeps
91+ # scan_for_annotated_workers from starting unrelated workers and lets the four
92+ # buckets run in parallel against one server without stealing each other's tasks.
93+ case " $bucket " in
94+ core)
95+ targets=(tests/integration)
96+ select=(" ${ai_ignore[@]} " ${perf_ignore[@]+" ${perf_ignore[@]} " } \
97+ --ignore=" $LEASE_SYNC " --ignore=" $LEASE_ASYNC " --ignore=" $TEST_ALL_FILE " )
98+ ;;
99+ all)
100+ targets=(tests/integration)
101+ select=(" ${ai_ignore[@]} " ${perf_ignore[@]+" ${perf_ignore[@]} " } )
102+ ;;
103+ long-sync)
104+ targets=(" $LEASE_SYNC " )
105+ select=(-m slow_sync)
106+ ;;
107+ long-async)
108+ targets=(" $LEASE_ASYNC " )
109+ select=(-m slow_async)
110+ ;;
111+ test-all)
112+ targets=(" $TEST_ALL_FILE " )
113+ select=(-m slow_test_all)
114+ ;;
115+ * )
116+ echo " Unknown --bucket='$bucket ' (expected: core, long-sync, long-async, test-all, all)" >&2
117+ exit 2
118+ ;;
119+ esac
120+
62121# Note: the "${arr[@]+"${arr[@]}"}" form is required so empty arrays don't trip
63122# "unbound variable" under `set -u` on bash 3.2 (the default macOS bash).
64- exec python3 -m pytest tests/integration -v \
65- --ignore=tests/integration/test_ai_task_types.py \
66- --ignore=tests/integration/test_ai_examples.py \
67- --ignore=tests/integration/test_agentic_workflows.py \
68- ${perf_ignore[@]+" ${perf_ignore[@]} " } \
123+ exec python3 -m pytest -v \
124+ " ${targets[@]} " \
125+ ${select[@]+" ${select[@]} " } \
69126 ${pytest_args[@]+" ${pytest_args[@]} " }
0 commit comments