diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 00000000..bc830247 --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,15 @@ +version: 'v0.4.0.{build}' + +build: off + +# This presumes that Git bash is installed at `C:\Program Files\Git` and the +# bash we're using is `C:\Program Files\Git\bin\bash.exe`. +# +# If instead it finds the Windows Subsystem for Linux bash at +# `C:\Windows\System32\bash.exe`, it will fail with an error like: +# /mnt/c/.../bats-core/test/test_helper.bash: line 1: +# syntax error near unexpected token `$'{\r'' +test_script: + - where bash + - bash --version + - bash -c 'time libexec/bats test' diff --git a/.travis.yml b/.travis.yml index db06d9d7..d7c534f6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,11 @@ -language: c -script: bin/bats --tap test +language: bash +os: +- linux +- osx + +script: +- bash -c 'time bin/bats --tap test' + notifications: email: on_success: never diff --git a/CONDUCT.md b/CONDUCT.md index 43c3dcb5..55343770 100644 --- a/CONDUCT.md +++ b/CONDUCT.md @@ -67,6 +67,11 @@ members of the project's leadership. ## Project Maintainers +### bats-core organization: +* Bianca Tamayo <> + + +## Project Original Author(s) * Sam Stephenson <> ## Attribution diff --git a/LICENSE b/LICENSE index bac4eb29..3ea56075 100644 --- a/LICENSE +++ b/LICENSE @@ -1,3 +1,24 @@ +Copyright (c) 2017 Bianca Tamayo and bats-core organization + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + Copyright (c) 2014 Sam Stephenson Permission is hereby granted, free of charge, to any person obtaining diff --git a/README.md b/README.md index 235bf1ee..15d9a2b9 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,34 @@ +## BATS-core: Bash Automated Testing System (2017) + +[![Build Status](https://travis-ci.org/bats-core/bats-core.svg?branch=master)](https://travis-ci.org/bats-core/bats-core) + +### Background: +### What is this repo? +**Tuesday, September 19, 2017:** This is a mirrored fork of [bats](https://github.com/sstephenson/bats), at [0360811](https://github.com/sstephenson/bats/commit/03608115df2071fff4eaaff1605768c275e5f81f). It was created via `git clone --bare` and `git push --mirror`. + +#### Why was it created? +The original bats repository needed new maintainers, and has not been actively maintained since 2013. While there were volunteers for maintainers, attempts to organize issues, and outstanding PRs, the lack of write-access to the repo hindered progress severely. + +## What's the plan and why? +The rough plan, originally [outlined here](https://github.com/sstephenson/bats/issues/150#issuecomment-323845404) is to create a new, mirrored mainline (this repo!). An excerpt: + +> **1. Roadmap 1.0:** +> There are already existing high-quality PRs, and often-requested features and issues, especially here at [#196](https://github.com/sstephenson/bats/issues/196). Leverage these and **consolidate into a single roadmap**. +> +>**2. Create or choose a fork or *mirror* of this repo to use as the new mainline:** +>Repoint existing PRs (whichever ones are possible) to the new mainline, get that repo to a stable 1.0. IMO we should create an organization and grant 2-3 people admin and write access. +> + +Doing it this way accomplishes two things: +1. Removes the dependency on the original maintainer +2. Enables collaboration and contribution flow again +3. Allows the possibility of merging back to original, or merging from original if or when the need arises +4. Prevents lock-out by giving administrative access to more than one person, increases transferability + +## Misc +- We are `#bats` on freenode + +--- # Bats: Bash Automated Testing System Bats is a [TAP](http://testanything.org)-compliant testing framework @@ -77,7 +108,7 @@ then iterates over the test cases and executes each one in its own process. For more details about how Bats evaluates test files, see -[Bats Evaluation Process](https://github.com/sstephenson/bats/wiki/Bats-Evaluation-Process) +[Bats Evaluation Process](https://github.com/bats-core/bats-core/wiki/Bats-Evaluation-Process) on the wiki. ### `run`: Test other commands @@ -210,8 +241,8 @@ Check out a copy of the Bats repository. Then, either add the Bats command with the location to the prefix in which you want to install Bats. For example, to install Bats into `/usr/local`, - $ git clone https://github.com/sstephenson/bats.git - $ cd bats + $ git clone https://github.com/bats-core/bats-core.git + $ cd bats-core $ ./install.sh /usr/local Note that you may need to run `install.sh` with `sudo` if you do not @@ -221,15 +252,15 @@ have permission to write to the installation prefix. ## Support The Bats source code repository is [hosted on -GitHub](https://github.com/sstephenson/bats). There you can file bugs +GitHub](https://github.com/bats-core/bats-core). There you can file bugs on the issue tracker or submit tested pull requests for review. For real-world examples from open-source projects using Bats, see -[Projects Using Bats](https://github.com/sstephenson/bats/wiki/Projects-Using-Bats) +[Projects Using Bats](https://github.com/bats-core/bats-core/wiki/Projects-Using-Bats) on the wiki. To learn how to set up your editor for Bats syntax highlighting, see -[Syntax Highlighting](https://github.com/sstephenson/bats/wiki/Syntax-Highlighting) +[Syntax Highlighting](https://github.com/bats-core/bats-core/wiki/Syntax-Highlighting) on the wiki. @@ -289,5 +320,9 @@ on the wiki. --- -© 2014 Sam Stephenson. Bats is released under an MIT-style license; +© 2017 Bianca Tamayo (bats-core organization) + +© 2014 Sam Stephenson + +Bats is released under an MIT-style license; see `LICENSE` for details. diff --git a/install.sh b/install.sh index 8bbdd16b..f366815b 100755 --- a/install.sh +++ b/install.sh @@ -2,7 +2,7 @@ set -e resolve_link() { - $(type -p greadlink readlink | head -1) "$1" + $(type -p greadlink readlink | head -n1) "$1" } abs_dirname() { diff --git a/libexec/bats b/libexec/bats index 71f392f7..e074747d 100755 --- a/libexec/bats +++ b/libexec/bats @@ -22,39 +22,62 @@ help() { echo " -t, --tap Show results in TAP format" echo " -v, --version Display the version number" echo - echo " For more information, see https://github.com/sstephenson/bats" + echo " For more information, see https://github.com/bats-core/bats-core" echo } +BATS_READLINK= + resolve_link() { - $(type -p greadlink readlink | head -1) "$1" + if [[ -z "$BATS_READLINK" ]]; then + if command -v 'greadlink' >/dev/null; then + BATS_READLINK='greadlink' + elif command -v 'readlink' >/dev/null; then + BATS_READLINK='readlink' + else + BATS_READLINK='true' + fi + fi + "$BATS_READLINK" "$1" || return 0 } abs_dirname() { - local cwd="$(pwd)" + local cwd="$PWD" local path="$1" while [ -n "$path" ]; do cd "${path%/*}" local name="${path##*/}" - path="$(resolve_link "$name" || true)" + path="$(resolve_link "$name")" done - pwd + printf -v "$2" -- '%s' "$PWD" cd "$cwd" } expand_path() { - { cd "$(dirname "$1")" 2>/dev/null - local dirname="$PWD" + local path="${1%/}" + local dirname="${path%/*}" + + if [[ "$dirname" == "$path" ]]; then + dirname="$PWD" + elif cd "$dirname" 2>/dev/null; then + dirname="$PWD" cd "$OLDPWD" - echo "$dirname/$(basename "$1")" - } || echo "$1" + else + printf '%s' "$path" + return + fi + printf -v "$2" '%s/%s' "$dirname" "${path##*/}" } -BATS_LIBEXEC="$(abs_dirname "$0")" -export BATS_PREFIX="$(abs_dirname "$BATS_LIBEXEC")" -export BATS_CWD="$(abs_dirname .)" +abs_dirname "$0" 'BATS_LIBEXEC' +abs_dirname "$BATS_LIBEXEC" 'BATS_PREFIX' +abs_dirname '.' 'BATS_CWD' + +export BATS_PREFIX +export BATS_CWD +export BATS_TEST_PATTERN='^ *@test +(.+) +\{ *(.*)$' export PATH="$BATS_LIBEXEC:$PATH" options=() @@ -113,14 +136,16 @@ fi filenames=() for filename in "${arguments[@]}"; do + expand_path "$filename" 'filename' + if [ -d "$filename" ]; then shopt -s nullglob - for suite_filename in "$(expand_path "$filename")"/*.bats; do + for suite_filename in "$filename"/*.bats; do filenames["${#filenames[@]}"]="$suite_filename" done shopt -u nullglob else - filenames["${#filenames[@]}"]="$(expand_path "$filename")" + filenames["${#filenames[@]}"]="$filename" fi done @@ -130,13 +155,11 @@ else command="bats-exec-suite" fi -if [ -n "$pretty" ]; then +set -o pipefail execfail +if [ -z "$pretty" ]; then + exec "$command" $count_flag "${filenames[@]}" +else extended_syntax_flag="-x" formatter="bats-format-tap-stream" -else - extended_syntax_flag="" - formatter="cat" + exec "$command" $count_flag $extended_syntax_flag "${filenames[@]}" | "$formatter" fi - -set -o pipefail execfail -exec "$command" $count_flag $extended_syntax_flag "${filenames[@]}" | "$formatter" diff --git a/libexec/bats-exec-suite b/libexec/bats-exec-suite index 29ab255d..96021bbd 100755 --- a/libexec/bats-exec-suite +++ b/libexec/bats-exec-suite @@ -17,7 +17,11 @@ trap "kill 0; exit 1" int count=0 for filename in "$@"; do - let count+="$(bats-exec-test -c "$filename")" + while IFS= read -r line; do + if [[ "$line" =~ $BATS_TEST_PATTERN ]]; then + let count+=1 + fi + done <"$filename" done if [ -n "$count_only_flag" ]; then diff --git a/libexec/bats-exec-test b/libexec/bats-exec-test index 8f3bd510..b88d4609 100755 --- a/libexec/bats-exec-test +++ b/libexec/bats-exec-test @@ -26,25 +26,54 @@ else shift fi -BATS_TEST_DIRNAME="$(dirname "$BATS_TEST_FILENAME")" +BATS_TEST_DIRNAME="${BATS_TEST_FILENAME%/*}" BATS_TEST_NAMES=() load() { local name="$1" local filename - if [ "${name:0:1}" = "/" ]; then - filename="${name}" - else - filename="$BATS_TEST_DIRNAME/${name}.bash" + # Argument is absolute, verify that the path exists and return after + # sourcing + if [[ "${name:0:1}" == "/" ]]; then + filename=$name + + if [[ ! -f "$filename" ]]; then + echo "bats: $filename does not exist" >&2 + exit 1 + fi + + source "$filename" + return fi - [ -f "$filename" ] || { - echo "bats: $filename does not exist" >&2 - exit 1 - } + # Set libpath with directory of current test file + # Defaults to BATS_LIB_PATH e.g. for testing + local libpath="${BATS_LIB_PATH:-$HOME/.bats/lib:/usr/lib/bats}" + libpath="$BATS_TEST_DIRNAME:$libpath" + + # Test for library in each libpath + for libdir in ${libpath//:/ }; do + dirname="$libdir/$name" + filename="$dirname.bash" - source "${filename}" + # Test for loading file of library + if [[ -f "$filename" ]]; then + source "$filename" + return + fi + + # Test for library and source all files within + if [[ -d "$dirname" ]]; then + for libfile in $dirname/*.bash; do + source $libfile + done + return + fi + done + + echo "bats: No file $name in BATS_LIB_PATH found" >&2 + exit 1 } run() { @@ -101,31 +130,33 @@ bats_capture_stack_trace() { local teardown_pattern=" teardown $BATS_TEST_SOURCE" local frame - local index=1 + local i - while frame="$(caller "$index")"; do + for ((i=2; i != ${#FUNCNAME[@]}; ++i)); do + frame="${BASH_LINENO[$((i-1))]} ${FUNCNAME[$i]} ${BASH_SOURCE[$i]}" BATS_CURRENT_STACK_TRACE["${#BATS_CURRENT_STACK_TRACE[@]}"]="$frame" if [[ "$frame" = *"$test_pattern" || \ "$frame" = *"$setup_pattern" || \ "$frame" = *"$teardown_pattern" ]]; then break - else - let index+=1 fi done - BATS_SOURCE="$(bats_frame_filename "${BATS_CURRENT_STACK_TRACE[0]}")" - BATS_LINENO="$(bats_frame_lineno "${BATS_CURRENT_STACK_TRACE[0]}")" + bats_frame_filename "${BATS_CURRENT_STACK_TRACE[0]}" 'BATS_SOURCE' + bats_frame_lineno "${BATS_CURRENT_STACK_TRACE[0]}" 'BATS_LINENO' } bats_print_stack_trace() { local frame local index=1 local count="${#@}" + local filename + local lineno for frame in "$@"; do - local filename="$(bats_trim_filename "$(bats_frame_filename "$frame")")" - local lineno="$(bats_frame_lineno "$frame")" + bats_frame_filename "$frame" 'filename' + bats_trim_filename "$filename" 'filename' + bats_frame_lineno "$frame" 'lineno' if [ $index -eq 1 ]; then echo -n "# (" @@ -133,7 +164,8 @@ bats_print_stack_trace() { echo -n "# " fi - local fn="$(bats_frame_function "$frame")" + local fn + bats_frame_function "$frame" 'fn' if [ "$fn" != "$BATS_TEST_NAME" ]; then echo -n "from function \`$fn' " fi @@ -151,12 +183,16 @@ bats_print_stack_trace() { bats_print_failed_command() { local frame="$1" local status="$2" - local filename="$(bats_frame_filename "$frame")" - local lineno="$(bats_frame_lineno "$frame")" + local filename + local lineno + local failed_line + local failed_command - local failed_line="$(bats_extract_line "$filename" "$lineno")" - local failed_command="$(bats_strip_string "$failed_line")" - echo -n "# \`${failed_command}' " + bats_frame_filename "$frame" 'filename' + bats_frame_lineno "$frame" 'lineno' + bats_extract_line "$filename" "$lineno" 'failed_line' + bats_strip_string "$failed_line" 'failed_command' + printf '%s' "# \`${failed_command}' " if [ $status -eq 1 ]; then echo "failed" @@ -166,49 +202,46 @@ bats_print_failed_command() { } bats_frame_lineno() { - local frame="$1" - local lineno="${frame%% *}" - echo "$lineno" + printf -v "$2" '%s' "${1%% *}" } bats_frame_function() { - local frame="$1" - local rest="${frame#* }" - local fn="${rest%% *}" - echo "$fn" + local __bff_function="${1#* }" + printf -v "$2" '%s' "${__bff_function%% *}" } bats_frame_filename() { - local frame="$1" - local rest="${frame#* }" - local filename="${rest#* }" + local __bff_filename="${1#* }" + __bff_filename="${__bff_filename#* }" - if [ "$filename" = "$BATS_TEST_SOURCE" ]; then - echo "$BATS_TEST_FILENAME" - else - echo "$filename" + if [ "$__bff_filename" = "$BATS_TEST_SOURCE" ]; then + __bff_filename="$BATS_TEST_FILENAME" fi + printf -v "$2" '%s' "$__bff_filename" } bats_extract_line() { - local filename="$1" - local lineno="$2" - sed -n "${lineno}p" "$filename" + local __bats_extract_line_line + local __bats_extract_line_index='0' + + while IFS= read -r __bats_extract_line_line; do + if [[ "$((++__bats_extract_line_index))" -eq "$2" ]]; then + printf -v "$3" '%s' "${__bats_extract_line_line%$'\r'}" + break + fi + done <"$1" } bats_strip_string() { - local string="$1" - printf "%s" "$string" | sed -e "s/^[ "$'\t'"]*//" -e "s/[ "$'\t'"]*$//" + [[ "$1" =~ ^[[:space:]]*(.*)[[:space:]]*$ ]] + printf -v "$2" '%s' "${BASH_REMATCH[1]}" } bats_trim_filename() { - local filename="$1" - local length="${#BATS_CWD}" - - if [ "${filename:0:length+1}" = "${BATS_CWD}/" ]; then - echo "${filename:length+1}" + if [[ "$1" =~ ^${BATS_CWD}/ ]]; then + printf -v "$2" '%s' "${1#$BATS_CWD/}" else - echo "$filename" + printf -v "$2" '%s' "$1" fi } @@ -218,13 +251,22 @@ bats_debug_trap() { fi } +# When running under Bash 3.2.57(1)-release on macOS, the `ERR` trap may not +# always fire, but the `EXIT` trap will. For this reason we call it at the very +# beginning of `bats_teardown_trap` (the `DEBUG` trap for the call will move +# `BATS_CURRENT_STACK_TRACE` to `BATS_PREVIOUS_STACK_TRACE`) and check the value +# of `$?` before taking other actions. bats_error_trap() { - BATS_ERROR_STATUS="$?" - BATS_ERROR_STACK_TRACE=( "${BATS_PREVIOUS_STACK_TRACE[@]}" ) - trap - debug + local status="$?" + if [[ "$status" -ne '0' ]]; then + BATS_ERROR_STATUS="$status" + BATS_ERROR_STACK_TRACE=( "${BATS_PREVIOUS_STACK_TRACE[@]}" ) + trap - debug + fi } bats_teardown_trap() { + bats_error_trap trap "bats_exit_trap" exit local status=0 teardown >>"$BATS_OUT" 2>&1 || status="$?" @@ -244,11 +286,10 @@ bats_exit_trap() { local skipped trap - err exit - skipped="" if [ -n "$BATS_TEST_SKIPPED" ]; then skipped=" # skip" if [ "1" != "$BATS_TEST_SKIPPED" ]; then - skipped+=" ($BATS_TEST_SKIPPED)" + skipped+=" $BATS_TEST_SKIPPED" fi fi @@ -259,7 +300,7 @@ bats_exit_trap() { sed -e "s/^/# /" < "$BATS_OUT" >&3 status=1 else - echo "ok ${BATS_TEST_NUMBER}${skipped} ${BATS_TEST_DESCRIPTION}" >&3 + echo "ok ${BATS_TEST_NUMBER} ${BATS_TEST_DESCRIPTION}${skipped}" >&3 status=0 fi @@ -280,7 +321,7 @@ bats_perform_tests() { bats_perform_test() { BATS_TEST_NAME="$1" - if [ "$(type -t "$BATS_TEST_NAME" || true)" = "function" ]; then + if declare -F "$BATS_TEST_NAME" >/dev/null; then BATS_TEST_NUMBER="$2" if [ -z "$BATS_TEST_NUMBER" ]; then echo "1..1" @@ -313,7 +354,7 @@ BATS_OUT="${BATS_TMPNAME}.out" bats_preprocess_source() { BATS_TEST_SOURCE="${BATS_TMPNAME}.src" - { tr -d '\r' < "$BATS_TEST_FILENAME"; echo; } | bats-preprocess > "$BATS_TEST_SOURCE" + . bats-preprocess <<< "$(< "$BATS_TEST_FILENAME")"$'\n' > "$BATS_TEST_SOURCE" trap "bats_cleanup_preprocessed_source" err exit trap "bats_cleanup_preprocessed_source; exit 1" int } diff --git a/libexec/bats-format-tap-stream b/libexec/bats-format-tap-stream index 614768f4..5d876cf0 100755 --- a/libexec/bats-format-tap-stream +++ b/libexec/bats-format-tap-stream @@ -65,9 +65,15 @@ log() { } summary() { - printf "\n%d test%s" "$count" "$(plural "$count")" + printf "\n%d test" "$count" + if [[ "$count" -ne '1' ]]; then + printf 's' + fi - printf ", %d failure%s" "$failures" "$(plural "$failures")" + printf ", %d failure" "$failures" + if [[ "$failures" -ne '1' ]]; then + printf 's' + fi if [ "$skipped" -gt 0 ]; then printf ", %d skipped" "$skipped" @@ -79,7 +85,9 @@ summary() { printf_with_truncation() { local width="$1" shift - local string="$(printf "$@")" + local string + + printf -v 'string' -- "$@" if [ "${#string}" -gt "$width" ]; then printf "%s..." "${string:0:$(( $width - 4 ))}" @@ -105,18 +113,18 @@ advance() { set_color() { local color="$1" - local weight="$2" - printf "\x1B[%d;%dm" $(( 30 + $color )) "$( [ "$weight" = "bold" ] && echo 1 || echo 22 )" + local weight='22' + + if [[ "$2" == 'bold' ]]; then + weight='1' + fi + printf "\x1B[%d;%dm" $(( 30 + $color )) "$weight" } clear_color() { printf "\x1B[0m" } -plural() { - [ "$1" -eq 1 ] || echo "s" -} - _buffer="" buffer() { @@ -144,7 +152,7 @@ while IFS= read -r line; do flush ;; "ok "* ) - skip_expr="ok $index # skip (\(([^)]*)\))?" + skip_expr="ok $index (.*) # skip ?(([^)]*))?" if [[ "$line" =~ $skip_expr ]]; then let skipped+=1 buffer skip "${BASH_REMATCH[2]}" diff --git a/libexec/bats-preprocess b/libexec/bats-preprocess index 04297ed0..8307b761 100755 --- a/libexec/bats-preprocess +++ b/libexec/bats-preprocess @@ -4,6 +4,7 @@ set -e encode_name() { local name="$1" local result="test_" + local hex_code if [[ ! "$name" =~ [^[:alnum:]\ _-] ]]; then name="${name//_/-5f}" @@ -21,27 +22,28 @@ encode_name() { elif [[ "$char" =~ [[:alnum:]] ]]; then result+="$char" else - result+="$(printf -- "-%02x" \'"$char")" + printf -v 'hex_code' -- "-%02x" \'"$char" + result+="$hex_code" fi done fi - echo "$result" + printf -v "$2" '%s' "$result" } tests=() index=0 -pattern='^ *@test *([^ ].*) *\{ *(.*)$' while IFS= read -r line; do + line="${line//$'\r'}" let index+=1 - if [[ "$line" =~ $pattern ]]; then - quoted_name="${BASH_REMATCH[1]}" + if [[ "$line" =~ $BATS_TEST_PATTERN ]]; then + name="${BASH_REMATCH[1]#[\'\"]}" + name="${name%[\'\"]}" body="${BASH_REMATCH[2]}" - name="$(eval echo "$quoted_name")" - encoded_name="$(encode_name "$name")" + encode_name "$name" 'encoded_name' tests["${#tests[@]}"]="$encoded_name" - echo "${encoded_name}() { bats_test_begin ${quoted_name} ${index}; ${body}" + echo "${encoded_name}() { bats_test_begin \"${name}\" ${index}; ${body}" else printf "%s\n" "$line" fi diff --git a/man/bats.1 b/man/bats.1 index 82f73016..3d4cb07a 100644 --- a/man/bats.1 +++ b/man/bats.1 @@ -89,12 +89,14 @@ ok 2 addition using dc The \fBbats\fR interpreter exits with a value of \fB0\fR if all test cases pass, or \fB1\fR if one or more test cases fail\. . .SH "SEE ALSO" -Bats wiki: \fIhttps://github\.com/sstephenson/bats/wiki/\fR +Bats wiki: \fIhttps://github\.com/bats\-core/bats\-core/wiki/\fR . .P \fBbash\fR(1), \fBbats\fR(7) . .SH "COPYRIGHT" + +(c) 2017 Bianca Tamayo (bats-core organization) (c) 2014 Sam Stephenson . .P diff --git a/man/bats.1.ronn b/man/bats.1.ronn index bd8f45b5..90dd62e9 100644 --- a/man/bats.1.ronn +++ b/man/bats.1.ronn @@ -93,7 +93,7 @@ or `1` if one or more test cases fail. SEE ALSO -------- -Bats wiki: _https://github.com/sstephenson/bats/wiki/_ +Bats wiki: _https://github.com/bats\-core/bats\-core/wiki/_ `bash`(1), `bats`(7) @@ -101,6 +101,7 @@ Bats wiki: _https://github.com/sstephenson/bats/wiki/_ COPYRIGHT --------- +(c) 2017 Bianca Tamayo (bats-core organization) (c) 2014 Sam Stephenson Bats is released under the terms of an MIT-style license. diff --git a/test/bats.bats b/test/bats.bats index f1aff293..e81b9b91 100755 --- a/test/bats.bats +++ b/test/bats.bats @@ -41,32 +41,52 @@ fixtures bats } @test "summary passing tests" { - run filter_control_sequences bats -p $FIXTURE_ROOT/passing.bats + run filter_control_sequences bats -p "$FIXTURE_ROOT/passing.bats" [ $status -eq 0 ] [ "${lines[1]}" = "1 test, 0 failures" ] } @test "summary passing and skipping tests" { - run filter_control_sequences bats -p $FIXTURE_ROOT/passing_and_skipping.bats + run filter_control_sequences bats -p "$FIXTURE_ROOT/passing_and_skipping.bats" [ $status -eq 0 ] - [ "${lines[2]}" = "2 tests, 0 failures, 1 skipped" ] + [ "${lines[3]}" = "3 tests, 0 failures, 2 skipped" ] +} + +@test "tap passing and skipping tests" { + run filter_control_sequences bats --tap "$FIXTURE_ROOT/passing_and_skipping.bats" + [ $status -eq 0 ] + [ "${lines[0]}" = "1..3" ] + [ "${lines[1]}" = "ok 1 a passing test" ] + [ "${lines[2]}" = "ok 2 a skipped test with no reason # skip" ] + [ "${lines[3]}" = "ok 3 a skipped test with a reason # skip for a really good reason" ] } @test "summary passing and failing tests" { - run filter_control_sequences bats -p $FIXTURE_ROOT/failing_and_passing.bats + run filter_control_sequences bats -p "$FIXTURE_ROOT/failing_and_passing.bats" [ $status -eq 0 ] [ "${lines[4]}" = "2 tests, 1 failure" ] } @test "summary passing, failing and skipping tests" { - run filter_control_sequences bats -p $FIXTURE_ROOT/passing_failing_and_skipping.bats + run filter_control_sequences bats -p "$FIXTURE_ROOT/passing_failing_and_skipping.bats" [ $status -eq 0 ] [ "${lines[5]}" = "3 tests, 1 failure, 1 skipped" ] } +@test "tap passing, failing and skipping tests" { + run filter_control_sequences bats --tap $FIXTURE_ROOT/passing_failing_and_skipping.bats + [ $status -eq 0 ] + [ "${lines[0]}" = "1..3" ] + [ "${lines[1]}" = "ok 1 a passing test" ] + [ "${lines[2]}" = "ok 2 a skipping test # skip" ] + [ "${lines[3]}" = "not ok 3 a failing test" ] +} + @test "one failing test" { run bats "$FIXTURE_ROOT/failing.bats" [ $status -eq 1 ] + printf 'lines:\n' >&2 + printf '%s\n' "${lines[@]}" >&2 [ "${lines[0]}" = '1..1' ] [ "${lines[1]}" = 'not ok 1 a failing test' ] [ "${lines[2]}" = "# (in test file $RELATIVE_FIXTURE_ROOT/failing.bats, line 4)" ] @@ -86,6 +106,8 @@ fixtures bats @test "failing test with significant status" { STATUS=2 run bats "$FIXTURE_ROOT/failing.bats" [ $status -eq 1 ] + printf 'lines:\n' >&2 + printf '%s\n' "${lines[@]}" >&2 [ "${lines[3]}" = "# \`eval \"( exit \${STATUS:-1} )\"' failed with status 2" ] } @@ -153,6 +175,8 @@ fixtures bats cd "$TMP" run bats "$FIXTURE_ROOT/failing.bats" [ $status -eq 1 ] + printf 'lines:\n' >&2 + printf '%s\n' "${lines[@]}" >&2 [ "${lines[2]}" = "# (in test file $FIXTURE_ROOT/failing.bats, line 4)" ] } @@ -214,8 +238,8 @@ fixtures bats @test "skipped tests" { run bats "$FIXTURE_ROOT/skipped.bats" [ $status -eq 0 ] - [ "${lines[1]}" = "ok 1 # skip a skipped test" ] - [ "${lines[2]}" = "ok 2 # skip (a reason) a skipped test with a reason" ] + [ "${lines[1]}" = "ok 1 a skipped test # skip" ] + [ "${lines[2]}" = "ok 2 a skipped test with a reason # skip a reason" ] } @test "extended syntax" { @@ -262,3 +286,17 @@ fixtures bats [ $status -eq 0 ] [ "${lines[1]}" = "ok 1 loop_func" ] } + +@test "expand variables in test name" { + SUITE='test/suite' run bats "$FIXTURE_ROOT/expand_var_in_test_name.bats" + [ $status -eq 0 ] + [ "${lines[1]}" = "ok 1 test/suite: test with variable in name" ] +} + +@test "handle quoted and unquoted test names" { + run bats "$FIXTURE_ROOT/quoted_and_unquoted_test_names.bats" + [ $status -eq 0 ] + [ "${lines[1]}" = "ok 1 single-quoted name" ] + [ "${lines[2]}" = "ok 2 double-quoted name" ] + [ "${lines[3]}" = "ok 3 unquoted name" ] +} diff --git a/test/fixtures/bats/expand_var_in_test_name.bats b/test/fixtures/bats/expand_var_in_test_name.bats new file mode 100644 index 00000000..8f6dec23 --- /dev/null +++ b/test/fixtures/bats/expand_var_in_test_name.bats @@ -0,0 +1,3 @@ +@test "$SUITE: test with variable in name" { + true +} diff --git a/test/fixtures/bats/load.bats b/test/fixtures/bats/load.bats index 975b6b8c..45d6f0af 100644 --- a/test/fixtures/bats/load.bats +++ b/test/fixtures/bats/load.bats @@ -1,6 +1,27 @@ [ -n "$HELPER_NAME" ] || HELPER_NAME="test_helper" load "$HELPER_NAME" +BATS_LIB_PATH="$BATS_TEST_DIRNAME/load_path" \ + load "${HELPER_LIB_SINGLE_FILE:-single_file}" + +BATS_LIB_PATH="$BATS_TEST_DIRNAME/load_path" \ + load "${HELPER_LIB_NO_LOADER:-no_loader}" + +BATS_LIB_PATH="$BATS_TEST_DIRNAME/load_path" \ + load "${HELPER_LIB_WITH_LOADER:-with_loader}" + @test "calling a loaded helper" { help_me } + +@test "calling a library helper" { + lib_func +} + +@test "calling a helper from library without loading file" { + no_loader +} + +@test "calling a helper from library with loading file" { + with_loader +} diff --git a/test/fixtures/bats/load_path/no_loader/no_loader.bash b/test/fixtures/bats/load_path/no_loader/no_loader.bash new file mode 100644 index 00000000..2ee35060 --- /dev/null +++ b/test/fixtures/bats/load_path/no_loader/no_loader.bash @@ -0,0 +1,3 @@ +no_loader() { + true +} diff --git a/test/fixtures/bats/load_path/single_file.bash b/test/fixtures/bats/load_path/single_file.bash new file mode 100644 index 00000000..5a170e13 --- /dev/null +++ b/test/fixtures/bats/load_path/single_file.bash @@ -0,0 +1,3 @@ +lib_func() { + true +} diff --git a/test/fixtures/bats/load_path/with_loader.bash b/test/fixtures/bats/load_path/with_loader.bash new file mode 100644 index 00000000..ba4d78ec --- /dev/null +++ b/test/fixtures/bats/load_path/with_loader.bash @@ -0,0 +1 @@ +source "$(dirname ${BASH_SOURCE[0]})/with_loader/a-file.bash" diff --git a/test/fixtures/bats/load_path/with_loader/a-file.bash b/test/fixtures/bats/load_path/with_loader/a-file.bash new file mode 100644 index 00000000..12fbd141 --- /dev/null +++ b/test/fixtures/bats/load_path/with_loader/a-file.bash @@ -0,0 +1,3 @@ +with_loader() { + true +} diff --git a/test/fixtures/bats/passing_and_skipping.bats b/test/fixtures/bats/passing_and_skipping.bats index 88d74bef..83fc76bf 100644 --- a/test/fixtures/bats/passing_and_skipping.bats +++ b/test/fixtures/bats/passing_and_skipping.bats @@ -2,6 +2,10 @@ true } -@test "a skipping test" { +@test "a skipped test with no reason" { skip } + +@test "a skipped test with a reason" { + skip "for a really good reason" +} diff --git a/test/fixtures/bats/quoted_and_unquoted_test_names.bats b/test/fixtures/bats/quoted_and_unquoted_test_names.bats new file mode 100644 index 00000000..aa460daa --- /dev/null +++ b/test/fixtures/bats/quoted_and_unquoted_test_names.bats @@ -0,0 +1,11 @@ +@test 'single-quoted name' { + true +} + +@test "double-quoted name" { + true +} + +@test unquoted name { + true +} diff --git a/test/test_helper.bash b/test/test_helper.bash index 84eee8c3..af890034 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -1,6 +1,6 @@ fixtures() { FIXTURE_ROOT="$BATS_TEST_DIRNAME/fixtures/$1" - RELATIVE_FIXTURE_ROOT="$(bats_trim_filename "$FIXTURE_ROOT")" + bats_trim_filename "$FIXTURE_ROOT" 'RELATIVE_FIXTURE_ROOT' } setup() { @@ -11,6 +11,13 @@ filter_control_sequences() { "$@" | sed $'s,\x1b\\[[0-9;]*[a-zA-Z],,g' } +if ! command -v tput >/dev/null; then + tput() { + printf '1000\n' + } + export -f tput +fi + teardown() { [ -d "$TMP" ] && rm -f "$TMP"/* }