test-lib: '--run' to run only specific tests
Allow better control of the set of tests that will be executed for a single test suite. Mostly useful while debugging or developing as it allows to focus on a specific test. Signed-off-by: Ilya Bobyr <ilya.bobyr@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Ilya Bobyr committed
Apr 30, 2014 at 02:50 UTC
0445e6f0a1223b5d40542627607207a87a416b5b
3 files changed
+537
-8
t/README
+77
-4
@@ -104,6 +104,12 @@ appropriately before running "make".
104
This causes additional long-running tests to be run (where
105
available), for more exhaustive testing.
106
107
+-r::
108
+--run=<test-selector>::
109
+ Run only the subset of tests indicated by
110
+ <test-selector>. See section "Skipping Tests" below for
111
+ <test-selector> syntax.
112
+
113
--valgrind=<tool>::
114
Execute all Git binaries under valgrind tool <tool> and exit
115
with status 126 on errors (just like regular tests, this will
@@ -191,10 +197,77 @@ and either can match the "t[0-9]{4}" part to skip the whole
197
test, or t[0-9]{4} followed by ".$number" to say which
198
particular test to skip.
199
194
-Note that some tests in the existing test suite rely on previous
195
-test item, so you cannot arbitrarily disable one and expect the
196
-remainder of test to check what the test originally was intended
197
-to check.
200
+For an individual test suite --run could be used to specify that
201
+only some tests should be run or that some tests should be
202
+excluded from a run.
203
+
204
+The argument for --run is a list of individual test numbers or
205
+ranges with an optional negation prefix that define what tests in
206
+a test suite to include in the run. A range is two numbers
207
+separated with a dash and matches a range of tests with both ends
208
+been included. You may omit the first or the second number to
209
+mean "from the first test" or "up to the very last test"
210
+respectively.
211
+
212
+Optional prefix of '!' means that the test or a range of tests
213
+should be excluded from the run.
214
+
215
+If --run starts with an unprefixed number or range the initial
216
+set of tests to run is empty. If the first item starts with '!'
217
+all the tests are added to the initial set. After initial set is
218
+determined every test number or range is added or excluded from
219
+the set one by one, from left to right.
220
+
221
+Individual numbers or ranges could be separated either by a space
222
+or a comma.
223
+
224
+For example, to run only tests up to a specific test (21), one
225
+could do this:
226
+
227
+ $ sh ./t9200-git-cvsexport-commit.sh --run='1-21'
228
+
229
+or this:
230
+
231
+ $ sh ./t9200-git-cvsexport-commit.sh --run='-21'
232
+
233
+Common case is to run several setup tests (1, 2, 3) and then a
234
+specific test (21) that relies on that setup:
235
+
236
+ $ sh ./t9200-git-cvsexport-commit.sh --run='1 2 3 21'
237
+
238
+or:
239
+
240
+ $ sh ./t9200-git-cvsexport-commit.sh --run=1,2,3,21
241
+
242
+or:
243
+
244
+ $ sh ./t9200-git-cvsexport-commit.sh --run='-3 21'
245
+
246
+As noted above, the test set is built going though items left to
247
+right, so this:
248
+
249
+ $ sh ./t9200-git-cvsexport-commit.sh --run='1-4 !3'
250
+
251
+will run tests 1, 2, and 4. Items that comes later have higher
252
+precendence. It means that this:
253
+
254
+ $ sh ./t9200-git-cvsexport-commit.sh --run='!3 1-4'
255
+
256
+would just run tests from 1 to 4, including 3.
257
+
258
+You may use negation with ranges. The following will run all
259
+test in the test suite except from 7 up to 11:
260
+
261
+ $ sh ./t9200-git-cvsexport-commit.sh --run='!7-11'
262
+
263
+Some tests in a test suite rely on the previous tests performing
264
+certain actions, specifically some tests are designated as
265
+"setup" test, so you cannot _arbitrarily_ disable one test and
266
+expect the rest to function correctly.
267
+
268
+--run is mostly useful when you want to focus on a specific test
269
+and know what setup is needed for it. Or when you want to run
270
+everything up to a certain test.
271
272
273
Naming Tests
t/t0000-basic.sh
+352
-4
@@ -42,9 +42,9 @@ test_expect_success 'success is reported like this' '
42
:
43
'
44
45
-run_sub_test_lib_test () {
46
- name="$1" descr="$2" # stdin is the body of the test code
47
- shift 2
45
+_run_sub_test_lib_test_common () {
46
+ neg="$1" name="$2" descr="$3" # stdin is the body of the test code
47
+ shift 3
48
mkdir "$name" &&
49
(
50
# Pretend we're not running under a test harness, whether we
@@ -70,10 +70,23 @@ run_sub_test_lib_test () {
70
export TEST_DIRECTORY &&
71
TEST_OUTPUT_DIRECTORY=$(pwd) &&
72
export TEST_OUTPUT_DIRECTORY &&
73
- ./"$name.sh" "$@" >out 2>err
73
+ if test -z "$neg"
74
+ then
75
+ ./"$name.sh" "$@" >out 2>err
76
+ else
77
+ ! ./"$name.sh" "$@" >out 2>err
78
+ fi
79
)
80
}
81
82
+run_sub_test_lib_test () {
83
+ _run_sub_test_lib_test_common '' "$@"
84
+}
85
+
86
+run_sub_test_lib_test_err () {
87
+ _run_sub_test_lib_test_common '!' "$@"
88
+}
89
+
90
check_sub_test_lib_test () {
91
name="$1" # stdin is the expected output from the test
92
(
@@ -84,6 +97,18 @@ check_sub_test_lib_test () {
97
)
98
}
99
100
+check_sub_test_lib_test_err () {
101
+ name="$1" # stdin is the expected output output from the test
102
+ # expected error output is in descriptior 3
103
+ (
104
+ cd "$name" &&
105
+ sed -e 's/^> //' -e 's/Z$//' >expect.out &&
106
+ test_cmp expect.out out &&
107
+ sed -e 's/^> //' -e 's/Z$//' <&3 >expect.err &&
108
+ test_cmp expect.err err
109
+ )
110
+}
111
+
112
test_expect_success 'pretend we have a fully passing test suite' "
113
run_sub_test_lib_test full-pass '3 passing tests' <<-\\EOF &&
114
for i in 1 2 3
@@ -333,6 +358,329 @@ test_expect_success 'GIT_SKIP_TESTS sh pattern' "
358
EOF
359
"
360
361
+test_expect_success '--run basic' "
362
+ run_sub_test_lib_test run-basic \
363
+ '--run basic' --run='1 3 5' <<-\\EOF &&
364
+ for i in 1 2 3 4 5 6
365
+ do
366
+ test_expect_success \"passing test #\$i\" 'true'
367
+ done
368
+ test_done
369
+ EOF
370
+ check_sub_test_lib_test run-basic <<-\\EOF
371
+ > ok 1 - passing test #1
372
+ > ok 2 # skip passing test #2 (--run)
373
+ > ok 3 - passing test #3
374
+ > ok 4 # skip passing test #4 (--run)
375
+ > ok 5 - passing test #5
376
+ > ok 6 # skip passing test #6 (--run)
377
+ > # passed all 6 test(s)
378
+ > 1..6
379
+ EOF
380
+"
381
+
382
+test_expect_success '--run with a range' "
383
+ run_sub_test_lib_test run-range \
384
+ '--run with a range' --run='1-3' <<-\\EOF &&
385
+ for i in 1 2 3 4 5 6
386
+ do
387
+ test_expect_success \"passing test #\$i\" 'true'
388
+ done
389
+ test_done
390
+ EOF
391
+ check_sub_test_lib_test run-range <<-\\EOF
392
+ > ok 1 - passing test #1
393
+ > ok 2 - passing test #2
394
+ > ok 3 - passing test #3
395
+ > ok 4 # skip passing test #4 (--run)
396
+ > ok 5 # skip passing test #5 (--run)
397
+ > ok 6 # skip passing test #6 (--run)
398
+ > # passed all 6 test(s)
399
+ > 1..6
400
+ EOF
401
+"
402
+
403
+test_expect_success '--run with two ranges' "
404
+ run_sub_test_lib_test run-two-ranges \
405
+ '--run with two ranges' --run='1-2 5-6' <<-\\EOF &&
406
+ for i in 1 2 3 4 5 6
407
+ do
408
+ test_expect_success \"passing test #\$i\" 'true'
409
+ done
410
+ test_done
411
+ EOF
412
+ check_sub_test_lib_test run-two-ranges <<-\\EOF
413
+ > ok 1 - passing test #1
414
+ > ok 2 - passing test #2
415
+ > ok 3 # skip passing test #3 (--run)
416
+ > ok 4 # skip passing test #4 (--run)
417
+ > ok 5 - passing test #5
418
+ > ok 6 - passing test #6
419
+ > # passed all 6 test(s)
420
+ > 1..6
421
+ EOF
422
+"
423
+
424
+test_expect_success '--run with a left open range' "
425
+ run_sub_test_lib_test run-left-open-range \
426
+ '--run with a left open range' --run='-3' <<-\\EOF &&
427
+ for i in 1 2 3 4 5 6
428
+ do
429
+ test_expect_success \"passing test #\$i\" 'true'
430
+ done
431
+ test_done
432
+ EOF
433
+ check_sub_test_lib_test run-left-open-range <<-\\EOF
434
+ > ok 1 - passing test #1
435
+ > ok 2 - passing test #2
436
+ > ok 3 - passing test #3
437
+ > ok 4 # skip passing test #4 (--run)
438
+ > ok 5 # skip passing test #5 (--run)
439
+ > ok 6 # skip passing test #6 (--run)
440
+ > # passed all 6 test(s)
441
+ > 1..6
442
+ EOF
443
+"
444
+
445
+test_expect_success '--run with a right open range' "
446
+ run_sub_test_lib_test run-right-open-range \
447
+ '--run with a right open range' --run='4-' <<-\\EOF &&
448
+ for i in 1 2 3 4 5 6
449
+ do
450
+ test_expect_success \"passing test #\$i\" 'true'
451
+ done
452
+ test_done
453
+ EOF
454
+ check_sub_test_lib_test run-right-open-range <<-\\EOF
455
+ > ok 1 # skip passing test #1 (--run)
456
+ > ok 2 # skip passing test #2 (--run)
457
+ > ok 3 # skip passing test #3 (--run)
458
+ > ok 4 - passing test #4
459
+ > ok 5 - passing test #5
460
+ > ok 6 - passing test #6
461
+ > # passed all 6 test(s)
462
+ > 1..6
463
+ EOF
464
+"
465
+
466
+test_expect_success '--run with basic negation' "
467
+ run_sub_test_lib_test run-basic-neg \
468
+ '--run with basic negation' --run='"'!3'"' <<-\\EOF &&
469
+ for i in 1 2 3 4 5 6
470
+ do
471
+ test_expect_success \"passing test #\$i\" 'true'
472
+ done
473
+ test_done
474
+ EOF
475
+ check_sub_test_lib_test run-basic-neg <<-\\EOF
476
+ > ok 1 - passing test #1
477
+ > ok 2 - passing test #2
478
+ > ok 3 # skip passing test #3 (--run)
479
+ > ok 4 - passing test #4
480
+ > ok 5 - passing test #5
481
+ > ok 6 - passing test #6
482
+ > # passed all 6 test(s)
483
+ > 1..6
484
+ EOF
485
+"
486
+
487
+test_expect_success '--run with two negations' "
488
+ run_sub_test_lib_test run-two-neg \
489
+ '--run with two negations' --run='"'!3 !6'"' <<-\\EOF &&
490
+ for i in 1 2 3 4 5 6
491
+ do
492
+ test_expect_success \"passing test #\$i\" 'true'
493
+ done
494
+ test_done
495
+ EOF
496
+ check_sub_test_lib_test run-two-neg <<-\\EOF
497
+ > ok 1 - passing test #1
498
+ > ok 2 - passing test #2
499
+ > ok 3 # skip passing test #3 (--run)
500
+ > ok 4 - passing test #4
501
+ > ok 5 - passing test #5
502
+ > ok 6 # skip passing test #6 (--run)
503
+ > # passed all 6 test(s)
504
+ > 1..6
505
+ EOF
506
+"
507
+
508
+test_expect_success '--run a range and negation' "
509
+ run_sub_test_lib_test run-range-and-neg \
510
+ '--run a range and negation' --run='"'-4 !2'"' <<-\\EOF &&
511
+ for i in 1 2 3 4 5 6
512
+ do
513
+ test_expect_success \"passing test #\$i\" 'true'
514
+ done
515
+ test_done
516
+ EOF
517
+ check_sub_test_lib_test run-range-and-neg <<-\\EOF
518
+ > ok 1 - passing test #1
519
+ > ok 2 # skip passing test #2 (--run)
520
+ > ok 3 - passing test #3
521
+ > ok 4 - passing test #4
522
+ > ok 5 # skip passing test #5 (--run)
523
+ > ok 6 # skip passing test #6 (--run)
524
+ > # passed all 6 test(s)
525
+ > 1..6
526
+ EOF
527
+"
528
+
529
+test_expect_success '--run range negation' "
530
+ run_sub_test_lib_test run-range-neg \
531
+ '--run range negation' --run='"'!1-3'"' <<-\\EOF &&
532
+ for i in 1 2 3 4 5 6
533
+ do
534
+ test_expect_success \"passing test #\$i\" 'true'
535
+ done
536
+ test_done
537
+ EOF
538
+ check_sub_test_lib_test run-range-neg <<-\\EOF
539
+ > ok 1 # skip passing test #1 (--run)
540
+ > ok 2 # skip passing test #2 (--run)
541
+ > ok 3 # skip passing test #3 (--run)
542
+ > ok 4 - passing test #4
543
+ > ok 5 - passing test #5
544
+ > ok 6 - passing test #6
545
+ > # passed all 6 test(s)
546
+ > 1..6
547
+ EOF
548
+"
549
+
550
+test_expect_success '--run include, exclude and include' "
551
+ run_sub_test_lib_test run-inc-neg-inc \
552
+ '--run include, exclude and include' \
553
+ --run='"'1-5 !1-3 2'"' <<-\\EOF &&
554
+ for i in 1 2 3 4 5 6
555
+ do
556
+ test_expect_success \"passing test #\$i\" 'true'
557
+ done
558
+ test_done
559
+ EOF
560
+ check_sub_test_lib_test run-inc-neg-inc <<-\\EOF
561
+ > ok 1 # skip passing test #1 (--run)
562
+ > ok 2 - passing test #2
563
+ > ok 3 # skip passing test #3 (--run)
564
+ > ok 4 - passing test #4
565
+ > ok 5 - passing test #5
566
+ > ok 6 # skip passing test #6 (--run)
567
+ > # passed all 6 test(s)
568
+ > 1..6
569
+ EOF
570
+"
571
+
572
+test_expect_success '--run include, exclude and include, comma separated' "
573
+ run_sub_test_lib_test run-inc-neg-inc-comma \
574
+ '--run include, exclude and include, comma separated' \
575
+ --run=1-5,\!1-3,2 <<-\\EOF &&
576
+ for i in 1 2 3 4 5 6
577
+ do
578
+ test_expect_success \"passing test #\$i\" 'true'
579
+ done
580
+ test_done
581
+ EOF
582
+ check_sub_test_lib_test run-inc-neg-inc-comma <<-\\EOF
583
+ > ok 1 # skip passing test #1 (--run)
584
+ > ok 2 - passing test #2
585
+ > ok 3 # skip passing test #3 (--run)
586
+ > ok 4 - passing test #4
587
+ > ok 5 - passing test #5
588
+ > ok 6 # skip passing test #6 (--run)
589
+ > # passed all 6 test(s)
590
+ > 1..6
591
+ EOF
592
+"
593
+
594
+test_expect_success '--run exclude and include' "
595
+ run_sub_test_lib_test run-neg-inc \
596
+ '--run exclude and include' \
597
+ --run='"'!3- 5'"' <<-\\EOF &&
598
+ for i in 1 2 3 4 5 6
599
+ do
600
+ test_expect_success \"passing test #\$i\" 'true'
601
+ done
602
+ test_done
603
+ EOF
604
+ check_sub_test_lib_test run-neg-inc <<-\\EOF
605
+ > ok 1 - passing test #1
606
+ > ok 2 - passing test #2
607
+ > ok 3 # skip passing test #3 (--run)
608
+ > ok 4 # skip passing test #4 (--run)
609
+ > ok 5 - passing test #5
610
+ > ok 6 # skip passing test #6 (--run)
611
+ > # passed all 6 test(s)
612
+ > 1..6
613
+ EOF
614
+"
615
+
616
+test_expect_success '--run empty selectors' "
617
+ run_sub_test_lib_test run-empty-sel \
618
+ '--run empty selectors' \
619
+ --run='1,,3,,,5' <<-\\EOF &&
620
+ for i in 1 2 3 4 5 6
621
+ do
622
+ test_expect_success \"passing test #\$i\" 'true'
623
+ done
624
+ test_done
625
+ EOF
626
+ check_sub_test_lib_test run-empty-sel <<-\\EOF
627
+ > ok 1 - passing test #1
628
+ > ok 2 # skip passing test #2 (--run)
629
+ > ok 3 - passing test #3
630
+ > ok 4 # skip passing test #4 (--run)
631
+ > ok 5 - passing test #5
632
+ > ok 6 # skip passing test #6 (--run)
633
+ > # passed all 6 test(s)
634
+ > 1..6
635
+ EOF
636
+"
637
+
638
+test_expect_success '--run invalid range start' "
639
+ run_sub_test_lib_test_err run-inv-range-start \
640
+ '--run invalid range start' \
641
+ --run='a-5' <<-\\EOF &&
642
+ test_expect_success \"passing test #1\" 'true'
643
+ test_done
644
+ EOF
645
+ check_sub_test_lib_test_err run-inv-range-start \
646
+ <<-\\EOF_OUT 3<<-\\EOF_ERR
647
+ > FATAL: Unexpected exit with code 1
648
+ EOF_OUT
649
+ > error: --run: invalid non-numeric in range start: 'a-5'
650
+ EOF_ERR
651
+"
652
+
653
+test_expect_success '--run invalid range end' "
654
+ run_sub_test_lib_test_err run-inv-range-end \
655
+ '--run invalid range end' \
656
+ --run='1-z' <<-\\EOF &&
657
+ test_expect_success \"passing test #1\" 'true'
658
+ test_done
659
+ EOF
660
+ check_sub_test_lib_test_err run-inv-range-end \
661
+ <<-\\EOF_OUT 3<<-\\EOF_ERR
662
+ > FATAL: Unexpected exit with code 1
663
+ EOF_OUT
664
+ > error: --run: invalid non-numeric in range end: '1-z'
665
+ EOF_ERR
666
+"
667
+
668
+test_expect_success '--run invalid selector' "
669
+ run_sub_test_lib_test_err run-inv-selector \
670
+ '--run invalid selector' \
671
+ --run='1?' <<-\\EOF &&
672
+ test_expect_success \"passing test #1\" 'true'
673
+ test_done
674
+ EOF
675
+ check_sub_test_lib_test_err run-inv-selector \
676
+ <<-\\EOF_OUT 3<<-\\EOF_ERR
677
+ > FATAL: Unexpected exit with code 1
678
+ EOF_OUT
679
+ > error: --run: invalid non-numeric in test selector: '1?'
680
+ EOF_ERR
681
+"
682
+
683
+
684
test_set_prereq HAVEIT
685
haveit=no
686
test_expect_success HAVEIT 'test runs if prerequisite is satisfied' '
t/test-lib.sh
+108
@@ -191,6 +191,14 @@ do
191
immediate=t; shift ;;
192
-l|--l|--lo|--lon|--long|--long-|--long-t|--long-te|--long-tes|--long-test|--long-tests)
193
GIT_TEST_LONG=t; export GIT_TEST_LONG; shift ;;
194
+ -r)
195
+ shift; test "$#" -ne 0 || {
196
+ echo 'error: -r requires an argument' >&2;
197
+ exit 1;
198
+ }
199
+ run_list=$1; shift ;;
200
+ --run=*)
201
+ run_list=$(expr "z$1" : 'z[^=]*=\(.*\)'); shift ;;
202
-h|--h|--he|--hel|--help)
203
help=t; shift ;;
204
-v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose)
@@ -366,6 +374,99 @@ match_pattern_list () {
374
return 1
375
}
376
377
+match_test_selector_list () {
378
+ title="$1"
379
+ shift
380
+ arg="$1"
381
+ shift
382
+ test -z "$1" && return 0
383
+
384
+ # Both commas and whitespace are accepted as separators.
385
+ OLDIFS=$IFS
386
+ IFS=' ,'
387
+ set -- $1
388
+ IFS=$OLDIFS
389
+
390
+ # If the first selector is negative we include by default.
391
+ include=
392
+ case "$1" in
393
+ !*) include=t ;;
394
+ esac
395
+
396
+ for selector
397
+ do
398
+ orig_selector=$selector
399
+
400
+ positive=t
401
+ case "$selector" in
402
+ !*)
403
+ positive=
404
+ selector=${selector##?}
405
+ ;;
406
+ esac
407
+
408
+ test -z "$selector" && continue
409
+
410
+ case "$selector" in
411
+ *-*)
412
+ if expr "z${selector%%-*}" : "z[0-9]*[^0-9]" >/dev/null
413
+ then
414
+ echo "error: $title: invalid non-numeric in range" \
415
+ "start: '$orig_selector'" >&2
416
+ exit 1
417
+ fi
418
+ if expr "z${selector#*-}" : "z[0-9]*[^0-9]" >/dev/null
419
+ then
420
+ echo "error: $title: invalid non-numeric in range" \
421
+ "end: '$orig_selector'" >&2
422
+ exit 1
423
+ fi
424
+ ;;
425
+ *)
426
+ if expr "z$selector" : "z[0-9]*[^0-9]" >/dev/null
427
+ then
428
+ echo "error: $title: invalid non-numeric in test" \
429
+ "selector: '$orig_selector'" >&2
430
+ exit 1
431
+ fi
432
+ esac
433
+
434
+ # Short cut for "obvious" cases
435
+ test -z "$include" && test -z "$positive" && continue
436
+ test -n "$include" && test -n "$positive" && continue
437
+
438
+ case "$selector" in
439
+ -*)
440
+ if test $arg -le ${selector#-}
441
+ then
442
+ include=$positive
443
+ fi
444
+ ;;
445
+ *-)
446
+ if test $arg -ge ${selector%-}
447
+ then
448
+ include=$positive
449
+ fi
450
+ ;;
451
+ *-*)
452
+ if test ${selector%%-*} -le $arg \
453
+ && test $arg -le ${selector#*-}
454
+ then
455
+ include=$positive
456
+ fi
457
+ ;;
458
+ *)
459
+ if test $arg -eq $selector
460
+ then
461
+ include=$positive
462
+ fi
463
+ ;;
464
+ esac
465
+ done
466
+
467
+ test -n "$include"
468
+}
469
+
470
maybe_teardown_verbose () {
471
test -z "$verbose_only" && return
472
exec 4>/dev/null 3>/dev/null
@@ -470,6 +571,13 @@ test_skip () {
571
fi
572
skipped_reason="missing $missing_prereq${of_prereq}"
573
fi
574
+ if test -z "$to_skip" && test -n "$run_list" &&
575
+ ! match_test_selector_list '--run' $test_count "$run_list"
576
+ then
577
+ to_skip=t
578
+ skipped_reason="--run"
579
+ fi
580
+
581
case "$to_skip" in
582
t)
583
say_color skip >&3 "skipping test: $@"