Skip to content

Commit

Permalink
Add --rerun-failed
Browse files Browse the repository at this point in the history
  • Loading branch information
martin-schulze-vireso committed Aug 18, 2021
1 parent 1008e65 commit 4ed0e91
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 28 deletions.
3 changes: 3 additions & 0 deletions libexec/bats-core/bats
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ while [[ "$#" -ne 0 ]]; do
BATS_RUN_TMPDIR="$2"
shift
;;
--rerun-failed)
flags+=('--rerun-failed')
;;
-*)
abort "Bad command line option '$1'"
;;
Expand Down
11 changes: 10 additions & 1 deletion libexec/bats-core/bats-exec-file
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export flags=(--dummy-flag)
num_jobs=1
filter=''
extended_syntax=''
bats_rerun_failed=''

while [[ "$#" -ne 0 ]]; do
case "$1" in
Expand All @@ -30,6 +31,9 @@ while [[ "$#" -ne 0 ]]; do
# use singular to allow for users to override in file
BATS_NO_PARALLELIZE_WITHIN_FILE=1
;;
--rerun-failed)
bats_rerun_failed=1
;;
--dummy-flag)
;;
*)
Expand Down Expand Up @@ -273,7 +277,12 @@ bats_run_tests() {
if [[ $test_name ]]; then
((++test_number_in_suite))
((++test_number_in_file))
"$BATS_LIBEXEC/bats-exec-test" "${flags[@]}" "$filename" "$test_name" "$test_number_in_suite" "$test_number_in_file" || status=1
if ! "$BATS_LIBEXEC/bats-exec-test" "${flags[@]}" "$filename" "$test_name" "$test_number_in_suite" "$test_number_in_file"; then
if [[ -n "$bats_rerun_failed" ]]; then
printf "%s\t%s\n" "$filename" "$test_name" >> "${BATS_RERUN_FAILED_TMPFILE}"
fi
status=1
fi
fi
done
fi
Expand Down
88 changes: 61 additions & 27 deletions libexec/bats-core/bats-exec-suite
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ num_jobs=${BATS_NUMBER_OF_PARALLEL_JOBS-1}
have_gnu_parallel=
bats_no_parallelize_across_files=${BATS_NO_PARALLELIZE_ACROSS_FILES-}
bats_no_parallelize_within_files=
bats_rerun_failed=
flags=('--dummy-flag') # add a dummy flag to prevent unset varialeb errors on empty array expansion in old bash versions

abort() {
Expand Down Expand Up @@ -42,6 +43,10 @@ while [[ "$#" -ne 0 ]]; do
bats_no_parallelize_within_files=1
flags+=("--no-parallelize-within-files")
;;
--rerun-failed)
bats_rerun_failed=1
flags+=("--rerun-failed")
;;
--dummy-flag)
;;
*)
Expand All @@ -62,37 +67,60 @@ fi
# create a file that contains all (filtered) tests to run from all files
TESTS_LIST_FILE="${BATS_RUN_TMPDIR}/test_list_file.txt"

all_tests=()
for filename in "$@"; do
if [[ ! -f "$filename" ]]; then
abort "Test file \"${filename}\" does not exist"
fi

test_names=()
test_dupes=()
while read -r line; do
if [[ ! "$line" =~ ^bats_test_function\ ]]; then
continue
bats_gather_tests() {
all_tests=()
for filename in "$@"; do
if [[ ! -f "$filename" ]]; then
abort "Test file \"${filename}\" does not exist"
fi
line="${line%$'\r'}"
line="${line#* }"
test_line=$(printf "%s\t%s" "$filename" "$line")
all_tests+=("$test_line")
printf "%s\n" "$test_line" >>"$TESTS_LIST_FILE"
# avoid unbound variable errors on empty array expansion with old bash versions
if [[ ${#test_names[@]} -gt 0 && " ${test_names[*]} " == *" $line "* ]]; then
test_dupes+=("$line")
continue

test_names=()
test_dupes=()
while read -r line; do
if [[ ! "$line" =~ ^bats_test_function\ ]]; then
continue
fi
line="${line%$'\r'}"
line="${line#* }"
test_line=$(printf "%s\t%s" "$filename" "$line")
all_tests+=("$test_line")
printf "%s\n" "$test_line" >>"$TESTS_LIST_FILE"
# avoid unbound variable errors on empty array expansion with old bash versions
if [[ ${#test_names[@]} -gt 0 && " ${test_names[*]} " == *" $line "* ]]; then
test_dupes+=("$line")
continue
fi
test_names+=("$line")
done < <(BATS_TEST_FILTER="$filter" bats-preprocess "$filename")

if [[ "${#test_dupes[@]}" -ne 0 ]]; then
abort "Duplicate test name(s) in file \"${filename}\": ${test_dupes[*]}"
fi
test_names+=("$line")
done < <(BATS_TEST_FILTER="$filter" bats-preprocess "$filename")
done

if [[ "${#test_dupes[@]}" -ne 0 ]]; then
abort "Duplicate test name(s) in file \"${filename}\": ${test_dupes[*]}"
fi
done
test_count="${#all_tests[@]}"
}

test_count="${#all_tests[@]}"
export BATS_RERUN_FAILED_FILE="$PWD/.bats-rerun-failed-tests.list"
export BATS_RERUN_FAILED_TMPFILE="${BATS_RERUN_FAILED_FILE}.tmp"

if [[ -n "$bats_rerun_failed" ]]; then
if [[ -s "$BATS_RERUN_FAILED_FILE" ]]; then
test_count="$(wc -l < "$BATS_RERUN_FAILED_FILE")"
cp "$BATS_RERUN_FAILED_FILE" "$TESTS_LIST_FILE"
elif [[ -f "$BATS_RERUN_FAILED_FILE" ]]; then
printf "There where no failed tests in the last recorded run.\n" >&2
printf "Delete the file '%s' to run all tests again.\n" "${BATS_RERUN_FAILED_FILE#$PWD/}" >&2
printf "1..0\n"
exit 0
else
printf "No recording of previos runs found. Running all tests!\n" >&2
bats_gather_tests "$@"
fi
> $BATS_RERUN_FAILED_TMPFILE # truncate the file if it exists, else create
else
bats_gather_tests "$@"
fi

if [[ -n "$count_only_flag" ]]; then
printf '%d\n' "${test_count}"
Expand Down Expand Up @@ -157,4 +185,10 @@ else
done
fi

if [[ -n "$bats_rerun_failed" ]]; then
# only overwrite file once we finished with all tests
# else we would discard tests when aborting a test run with CTRL+C
mv "$BATS_RERUN_FAILED_TMPFILE" "$BATS_RERUN_FAILED_FILE"
fi

exit "$status"
27 changes: 27 additions & 0 deletions test/bats.bats
Original file line number Diff line number Diff line change
Expand Up @@ -1014,3 +1014,30 @@ EOF
run stars
[ "${lines[0]}" = '**' ]
}

@test "Without previous recording --rerun-failed runs all tests and then reruns only failed tests" {
cd "$BATS_TEST_TMPDIR" # don't pollute the source folder
run '=1' bats --rerun-failed "$FIXTURE_ROOT/passing_and_failing.bats"
# without previous recording, all tests should be run
[ "${lines[0]}" == 'No recording of previos runs found. Running all tests!' ]
[ "${lines[1]}" == '1..2' ]
[ "${lines[2]}" == 'ok 1 a passing test' ]
[ "${lines[3]}" == 'not ok 2 a failing test' ]

run '=1' bats --tap --rerun-failed "$FIXTURE_ROOT/passing_and_failing.bats"
# now we should only run the failing test
[ "${lines[0]}" == 1..1 ]
[ "${lines[1]}" == "not ok 1 a failing test" ]
}

@test "--rerun-failed gives warning on empty failed test list" {
cd "$BATS_TEST_TMPDIR" # don't pollute the source folder
# have no failing tests
run '=0' bats --rerun-failed "$FIXTURE_ROOT/passing.bats"
# try to rerun the empty list of failing tests
run '=0' bats --rerun-failed "$FIXTURE_ROOT/passing.bats"
[ "${lines[0]}" == "There where no failed tests in the last recorded run." ]
[ "${lines[1]}" == "Delete the file '.bats-rerun-failed-tests.list' to run all tests again." ]
[ "${lines[2]}" == "1..0" ]
[ "${#lines[@]}" -eq 3 ]
}

0 comments on commit 4ed0e91

Please sign in to comment.