@@ -26,6 +26,8 @@ KEEP_RUNNING=false
2626SELECTED_CORES=" "
2727INCLUDE_LOCAL_CORES=false
2828TEST_FILES=" "
29+ PARALLEL=false
30+ PARALLEL_WORKERS=" auto"
2931
3032# Function to print colored messages
3133print_message () {
@@ -57,6 +59,8 @@ OPTIONS:
5759 -k, --keep-running Keep containers running after tests
5860 -h, --html-coverage Generate HTML coverage report
5961 -f, --files Specify test files to run (can be used multiple times)
62+ -p, --parallel Run tests in parallel using pytest-xdist
63+ -w, --workers Number of parallel workers (default: auto)
6064 --help Show this help message
6165
6266EXAMPLES:
@@ -66,6 +70,8 @@ EXAMPLES:
6670 $0 external -k # Run external backends, keep containers
6771 $0 mongo memory -v # Run MongoDB and memory tests verbosely
6872 $0 all -f tests/test_main.py -f tests/test_redis_core_coverage.py # Run specific test files
73+ $0 memory pickle -p # Run local tests in parallel
74+ $0 all -p -w 4 # Run all tests with 4 parallel workers
6975
7076ENVIRONMENT:
7177 You can also set cores via CACHIER_TEST_CORES environment variable:
@@ -103,6 +109,20 @@ while [[ $# -gt 0 ]]; do
103109 usage
104110 exit 0
105111 ;;
112+ -p|--parallel)
113+ PARALLEL=true
114+ shift
115+ ;;
116+ -w|--workers)
117+ shift
118+ if [[ $# -eq 0 ]] || [[ " $1 " == -* ]]; then
119+ print_message $RED " Error: -w/--workers requires a number argument"
120+ usage
121+ exit 1
122+ fi
123+ PARALLEL_WORKERS=" $1 "
124+ shift
125+ ;;
106126 -* )
107127 print_message $RED " Unknown option: $1 "
108128 usage
@@ -234,6 +254,17 @@ check_dependencies() {
234254 }
235255 fi
236256
257+ # Check for pytest-xdist if parallel testing is requested
258+ if [ " $PARALLEL " = true ]; then
259+ if ! python -c " import xdist" 2> /dev/null; then
260+ print_message $YELLOW " Installing pytest-xdist for parallel testing..."
261+ pip install pytest-xdist || {
262+ print_message $RED " Failed to install pytest-xdist"
263+ exit 1
264+ }
265+ fi
266+ fi
267+
237268 # Check MongoDB dependencies if testing MongoDB
238269 if echo " $SELECTED_CORES " | grep -qw " mongo" ; then
239270 if ! python -c " import pymongo" 2> /dev/null; then
@@ -423,14 +454,20 @@ main() {
423454 # Check and install dependencies
424455 check_dependencies
425456
426- # Check if we need Docker
457+ # Check if we need Docker, and if we should run serial pickle tests
427458 needs_docker=false
459+ run_serial_local_tests=false
428460 for core in $SELECTED_CORES ; do
429461 case $core in
430462 mongo|redis|sql)
431463 needs_docker=true
432464 ;;
433465 esac
466+ case $core in
467+ pickle|all)
468+ run_serial_local_tests=true
469+ ;;
470+ esac
434471 done
435472
436473 if [ " $needs_docker " = true ]; then
@@ -497,15 +534,31 @@ main() {
497534 sql) test_sql ;;
498535 esac
499536 done
537+ if [ -n " $pytest_markers " ]; then
538+ pytest_markers=" ($pytest_markers ) and not seriallocal"
539+ else
540+ pytest_markers=" not seriallocal"
541+ fi
500542
501543 # Run pytest
502544 # Build pytest command
503545 PYTEST_CMD=" pytest"
546+ # and the specific pytest command for running serial pickle tests
547+ SERIAL_PYTEST_CMD=" pytest -m seriallocal"
548+ # Only add -n0 if pytest-xdist is available; otherwise, plain pytest is already serial
549+ if python - << 'EOF ' >/dev/null 2>&1
550+ import xdist # noqa: F401
551+ EOF
552+ then
553+ SERIAL_PYTEST_CMD=" $SERIAL_PYTEST_CMD -n0"
554+ fi
504555
505556 # Add test files if specified
506557 if [ -n " $TEST_FILES " ]; then
507558 PYTEST_CMD=" $PYTEST_CMD $TEST_FILES "
508559 print_message $BLUE " Test files specified: $TEST_FILES "
560+ # and turn off serial local tests, so we run only selected files
561+ run_serial_local_tests=false
509562 fi
510563
511564 # Add markers if needed (only if no specific test files were given)
@@ -517,6 +570,10 @@ main() {
517570
518571 if [ " $selected_sorted " != " $all_sorted " ]; then
519572 PYTEST_CMD=" $PYTEST_CMD -m \" $pytest_markers \" "
573+ else
574+ print_message $BLUE " Running all tests without markers since all cores are selected"
575+ PYTEST_CMD=" $PYTEST_CMD -m \" not seriallocal\" "
576+ run_serial_local_tests=true
520577 fi
521578 else
522579 # When test files are specified, still apply markers if not running all cores
@@ -532,15 +589,41 @@ main() {
532589 # Add verbose flag if needed
533590 if [ " $VERBOSE " = true ]; then
534591 PYTEST_CMD=" $PYTEST_CMD -v"
592+ SERIAL_PYTEST_CMD=" $SERIAL_PYTEST_CMD -v"
593+ fi
594+
595+ # Add parallel testing options if requested
596+ if [ " $PARALLEL " = true ]; then
597+ PYTEST_CMD=" $PYTEST_CMD -n $PARALLEL_WORKERS "
598+
599+ # Show parallel testing info
600+ if [ " $PARALLEL_WORKERS " = " auto" ]; then
601+ print_message $BLUE " Running tests in parallel with automatic worker detection"
602+ else
603+ print_message $BLUE " Running tests in parallel with $PARALLEL_WORKERS workers"
604+ fi
605+
606+ # Special note for pickle tests
607+ if echo " $SELECTED_CORES " | grep -qw " pickle" ; then
608+ print_message $YELLOW " Note: Pickle tests will use isolated cache directories for parallel safety"
609+ fi
535610 fi
536611
537612 # Add coverage options
538613 PYTEST_CMD=" $PYTEST_CMD --cov=cachier --cov-report=$COVERAGE_REPORT "
614+ SERIAL_PYTEST_CMD=" $SERIAL_PYTEST_CMD --cov=cachier --cov-report=$COVERAGE_REPORT --cov-append"
539615
540616 # Print and run the command
541617 print_message $BLUE " Running: $PYTEST_CMD "
542618 eval $PYTEST_CMD
543619
620+ if [ " $run_serial_local_tests " = true ]; then
621+ print_message $BLUE " Running serial local tests (pickle, memory) with: $SERIAL_PYTEST_CMD "
622+ eval $SERIAL_PYTEST_CMD
623+ else
624+ print_message $BLUE " Skipping serial local tests (pickle, memory) since not requested"
625+ fi
626+
544627 TEST_EXIT_CODE=$?
545628
546629 if [ $TEST_EXIT_CODE -eq 0 ]; then
0 commit comments