From 347f805ffdddab2ad849ef5ab70425a73ae0786d Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Sun, 20 Jul 2025 12:40:19 +0200 Subject: [PATCH 01/10] feat: add --doc option --- bashunit | 10 + docs/command-line.md | 17 + src/console_header.sh | 4 + src/doc.sh | 23 + tests/acceptance/bashunit_test.sh | 10 + ...est_bashunit_functional_benchmark.snapshot | 5 - ...test_bashunit_runs_benchmark_file.snapshot | 7 - ...nit_without_path_env_nor_argument.snapshot | 4 + ...it_should_display_all_assert_docs.snapshot | 1092 +++++++++++++++++ ...ould_display_filtered_assert_docs.snapshot | 118 ++ ...test_bashunit_should_display_help.snapshot | 4 + 11 files changed, 1282 insertions(+), 12 deletions(-) create mode 100644 src/doc.sh delete mode 100644 tests/acceptance/snapshots/bashunit_benchmark_test_sh.test_bashunit_functional_benchmark.snapshot delete mode 100644 tests/acceptance/snapshots/bashunit_benchmark_test_sh.test_bashunit_runs_benchmark_file.snapshot create mode 100644 tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_all_assert_docs.snapshot create mode 100644 tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_filtered_assert_docs.snapshot diff --git a/bashunit b/bashunit index 50827f00..51847f50 100755 --- a/bashunit +++ b/bashunit @@ -25,6 +25,7 @@ source "$BASHUNIT_ROOT_DIR/src/console_results.sh" source "$BASHUNIT_ROOT_DIR/src/helpers.sh" source "$BASHUNIT_ROOT_DIR/src/upgrade.sh" source "$BASHUNIT_ROOT_DIR/src/assertions.sh" +source "$BASHUNIT_ROOT_DIR/src/doc.sh" source "$BASHUNIT_ROOT_DIR/src/reports.sh" source "$BASHUNIT_ROOT_DIR/src/runner.sh" source "$BASHUNIT_ROOT_DIR/src/bashunit.sh" @@ -98,6 +99,15 @@ while [[ $# -gt 0 ]]; do console_header::print_version trap '' EXIT && exit 0 ;; + --doc) + if [[ -n ${2:-} && ${2:0:1} != "-" ]]; then + doc::print_asserts "$2" + shift + else + doc::print_asserts + fi + trap '' EXIT && exit 0 + ;; --upgrade) upgrade::upgrade trap '' EXIT && exit 0 diff --git a/docs/command-line.md b/docs/command-line.md index e4f86b37..ee58a341 100644 --- a/docs/command-line.md +++ b/docs/command-line.md @@ -370,6 +370,23 @@ Upgrade **bashunit** to latest version. ``` ::: +## Doc + +> `bashunit --doc [filter]` + +Display the documentation for assert functions. When `filter` is provided, +only matching asserts will be shown. + +::: code-group +```bash [Example] +./bashunit --doc equals +``` +```bash [Output] +## assert_equals +... +``` +::: + ## Init > `bashunit --init [dir]` diff --git a/src/console_header.sh b/src/console_header.sh index 2f64c2c9..ea4133f2 100644 --- a/src/console_header.sh +++ b/src/console_header.sh @@ -81,6 +81,10 @@ Options: -h, --help Show this help message. + --doc + Display the documentation for assert functions. When a filter is + provided, only matching asserts will be shown. + --init [dir] Generate a sample test suite in current or specified directory. diff --git a/src/doc.sh b/src/doc.sh new file mode 100644 index 00000000..d824191d --- /dev/null +++ b/src/doc.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +function doc::print_asserts() { + local search="${1:-}" + local doc_file="$BASHUNIT_ROOT_DIR/docs/assertions.md" + local line + local print=0 + while IFS='' read -r line || [[ -n "$line" ]]; do + if [[ $line =~ ^##\ (assert_[A-Za-z0-9_]+) ]]; then + local fn="${BASH_REMATCH[1]}" + if [[ -z "$search" || "$fn" == *"$search"* ]]; then + print=1 + echo "$line" + else + print=0 + fi + continue + fi + if [[ $print -eq 1 ]]; then + echo "$line" + fi + done < "$doc_file" +} diff --git a/tests/acceptance/bashunit_test.sh b/tests/acceptance/bashunit_test.sh index f5103cbe..32acfee5 100644 --- a/tests/acceptance/bashunit_test.sh +++ b/tests/acceptance/bashunit_test.sh @@ -18,3 +18,13 @@ function test_bashunit_should_display_help() { assert_match_snapshot "$(./bashunit --no-parallel --env "$TEST_ENV_FILE" --help)" assert_successful_code "$(./bashunit --no-parallel --env "$TEST_ENV_FILE" --help)" } + +function test_bashunit_should_display_all_assert_docs() { + assert_match_snapshot "$(./bashunit --no-parallel --env "$TEST_ENV_FILE" --doc)" + assert_successful_code "$(./bashunit --no-parallel --env "$TEST_ENV_FILE" --doc)" +} + +function test_bashunit_should_display_filtered_assert_docs() { + assert_match_snapshot "$(./bashunit --no-parallel --env "$TEST_ENV_FILE" --doc equals)" + assert_successful_code "$(./bashunit --no-parallel --env "$TEST_ENV_FILE" --doc equals)" +} diff --git a/tests/acceptance/snapshots/bashunit_benchmark_test_sh.test_bashunit_functional_benchmark.snapshot b/tests/acceptance/snapshots/bashunit_benchmark_test_sh.test_bashunit_functional_benchmark.snapshot deleted file mode 100644 index ebdd70f1..00000000 --- a/tests/acceptance/snapshots/bashunit_benchmark_test_sh.test_bashunit_functional_benchmark.snapshot +++ /dev/null @@ -1,5 +0,0 @@ -. - -Benchmark Results (avg ms) -Name Revs Its Avg(ms) -bench_run_bashunit_functional 2 1 ::ignore:: diff --git a/tests/acceptance/snapshots/bashunit_benchmark_test_sh.test_bashunit_runs_benchmark_file.snapshot b/tests/acceptance/snapshots/bashunit_benchmark_test_sh.test_bashunit_runs_benchmark_file.snapshot deleted file mode 100644 index fcecaece..00000000 --- a/tests/acceptance/snapshots/bashunit_benchmark_test_sh.test_bashunit_runs_benchmark_file.snapshot +++ /dev/null @@ -1,7 +0,0 @@ -bench bench_sleep [1/2] ::ignore:: -bench bench_sleep [2/2] ::ignore:: - - -Benchmark Results (avg ms) -Name Revs Its Avg(ms) -bench_sleep 5 2 ::ignore:: diff --git a/tests/acceptance/snapshots/bashunit_path_test_sh.test_bashunit_without_path_env_nor_argument.snapshot b/tests/acceptance/snapshots/bashunit_path_test_sh.test_bashunit_without_path_env_nor_argument.snapshot index 4e78a88f..fb87f7e8 100644 --- a/tests/acceptance/snapshots/bashunit_path_test_sh.test_bashunit_without_path_env_nor_argument.snapshot +++ b/tests/acceptance/snapshots/bashunit_path_test_sh.test_bashunit_without_path_env_nor_argument.snapshot @@ -28,6 +28,10 @@ Options: -h, --help Show this help message. + --doc + Display the documentation for assert functions. When a filter is + provided, only matching asserts will be shown. + --init [dir] Generate a sample test suite in current or specified directory. diff --git a/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_all_assert_docs.snapshot b/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_all_assert_docs.snapshot new file mode 100644 index 00000000..41e06605 --- /dev/null +++ b/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_all_assert_docs.snapshot @@ -0,0 +1,1092 @@ +## assert_true +> `assert_true bool|function|command` + +Reports an error if the argument result in a truthy value: `true` or `0`. + +- [assert_false](#assert-false) is similar but different. + +::: code-group +```bash [Example] +function test_success() { + assert_true true + assert_true 0 + assert_true "eval return 0" + assert_true mock_true +} + +function test_failure() { + assert_true false + assert_true 1 + assert_true "eval return 1" + assert_true mock_false +} +``` +```bash [globals.sh] +function mock_true() { + return 0 +} +function mock_false() { + return 1 +} +::: + +## assert_false +> `assert_false bool|function|command` + +Reports an error if the argument result in a falsy value: `false` or `1`. + +- [assert_true](#assert-true) is similar but different. + +::: code-group +```bash [Example] +function test_success() { + assert_false false + assert_false 1 + assert_false "eval return 1" + assert_false mock_false +} + +function test_failure() { + assert_false true + assert_false 0 + assert_false "eval return 0" + assert_false mock_true +} +``` +```bash [globals.sh] +function mock_true() { + return 0 +} +function mock_false() { + return 1 +} +``` +::: + +## assert_same +> `assert_same "expected" "actual"` + +Reports an error if the `expected` and `actual` are not the same - including special chars. + +- [assert_not_same](#assert-not-same) is the inverse of this assertion and takes the same arguments. +- [assert_equals](#assert-equals) is similar but ignoring the special chars. + +::: code-group +```bash [Example] +function test_success() { + assert_same "foo" "foo" +} + +function test_failure() { + assert_same "foo" "bar" +} +``` +::: + +## assert_equals +> `assert_equals "expected" "actual"` + +Reports an error if the two variables `expected` and `actual` are not equal ignoring the special chars like ANSI Escape Sequences (colors) and other special chars like tabs and new lines. + +- [assert_same](#assert-same) is similar but including special chars. + +::: code-group +```bash [Example] +function test_success() { + assert_equals "foo" "\e[31mfoo" +} + +function test_failure() { + assert_equals "\e[31mfoo" "\e[31mfoo" +} +``` +::: + +## assert_contains +> `assert_contains "needle" "haystack"` + +Reports an error if `needle` is not a substring of `haystack`. + +[assert_not_contains](#assert-not-contains) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + assert_contains "foo" "foobar" +} + +function test_failure() { + assert_contains "baz" "foobar" +} +``` + +::: + +## assert_contains_ignore_case +> `assert_contains_ignore_case "needle" "haystack"` + +Reports an error if `needle` is not a substring of `haystack`. +Differences in casing are ignored when needle is searched for in haystack. + +::: code-group +```bash [Example] +function test_success() { + assert_contains_ignore_case "foo" "FooBar" +} +function test_failure() { + assert_contains_ignore_case "baz" "FooBar" +} +``` +::: + +## assert_empty +> `assert_empty "actual"` + +Reports an error if `actual` is not empty. + +[assert_not_empty](#assert-not-empty) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + assert_empty "" +} + +function test_failure() { + assert_empty "foo" +} +``` +::: + +## assert_matches +> `assert_matches "pattern" "value"` + +Reports an error if `value` does not match the regular expression `pattern`. + +[assert_not_matches](#assert-not-matches) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + assert_matches "^foo" "foobar" +} + +function test_failure() { + assert_matches "^bar" "foobar" +} +``` +::: + +## assert_string_starts_with +> `assert_string_starts_with "needle" "haystack"` + +Reports an error if `haystack` does not starts with `needle`. + +[assert_string_not_starts_with](#assert-string-not-starts-with) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + assert_string_starts_with "foo" "foobar" +} + +function test_failure() { + assert_string_starts_with "baz" "foobar" +} +``` +::: + +## assert_string_ends_with +> `assert_string_ends_with "needle" "haystack"` + +Reports an error if `haystack` does not ends with `needle`. + +[assert_string_not_ends_with](#assert-string-not-ends-with) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + assert_string_ends_with "bar" "foobar" +} + +function test_failure() { + assert_string_ends_with "foo" "foobar" +} +``` +::: + +## assert_line_count +> `assert_line_count "count" "haystack"` + +Reports an error if `haystack` does not contain `count` lines. + +::: code-group +```bash [Example] +function test_success() { + local string="this is line one +this is line two +this is line three" + + assert_line_count 3 "$string" +} + +function test_failure() { + assert_line_count 2 "foobar" +} +``` +::: + +## assert_less_than +> `assert_less_than "expected" "actual"` + +Reports an error if `actual` is not less than `expected`. + +[assert_greater_than](#assert-greater-than) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + assert_less_than "999" "1" +} + +function test_failure() { + assert_less_than "1" "999" +} +``` +::: + +## assert_less_or_equal_than +> `assert_less_or_equal_than "expected" "actual"` + +Reports an error if `actual` is not less than or equal to `expected`. + +[assert_greater_than](#assert-greater-or-equal-than) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + assert_less_or_equal_than "999" "1" +} + +function test_success_with_two_equal_numbers() { + assert_less_or_equal_than "999" "999" +} + +function test_failure() { + assert_less_or_equal_than "1" "999" +} +``` +::: + +## assert_greater_than +> `assert_greater_than "expected" "actual"` + +Reports an error if `actual` is not greater than `expected`. + +[assert_less_than](#assert-less-than) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + assert_greater_than "1" "999" +} + +function test_failure() { + assert_greater_than "999" "1" +} +``` +::: + +## assert_greater_or_equal_than +> `assert_greater_or_equal_than "expected" "actual"` + +Reports an error if `actual` is not greater than or equal to `expected`. + +[assert_less_or_equal_than](#assert-less-or-equal-than) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + assert_greater_or_equal_than "1" "999" +} + +function test_success_with_two_equal_numbers() { + assert_greater_or_equal_than "999" "999" +} + +function test_failure() { + assert_greater_or_equal_than "999" "1" +} +``` +::: + +## assert_exit_code +> `assert_exit_code "expected" ["callable"]` + +Reports an error if the exit code of `callable` is not equal to `expected`. + +If `callable` is not provided, it takes the last executed command or function instead. + +[assert_successful_code](#assert-successful-code), [assert_general_error](#assert-general-error) and [assert_command_not_found](#assert-command-not-found) +are more semantic versions of this assertion, for which you don't need to specify an exit code. + +::: code-group +```bash [Example] +function test_success_with_callable() { + function foo() { + return 1 + } + + assert_exit_code "1" "$(foo)" +} + +function test_success_without_callable() { + function foo() { + return 1 + } + + foo # function took instead `callable` + + assert_exit_code "1" +} + +function test_failure() { + function foo() { + return 1 + } + + assert_exit_code "0" "$(foo)" +} +``` +::: + +## assert_array_contains +> `assert_array_contains "needle" "haystack"` + +Reports an error if `needle` is not an element of `haystack`. + +[assert_array_not_contains](#assert-array-not-contains) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + local haystack=(foo bar baz) + + assert_array_contains "bar" "${haystack[@]}" +} + +function test_failure() { + local haystack=(foo bar baz) + + assert_array_contains "foobar" "${haystack[@]}" +} +``` +::: + +## assert_successful_code +> `assert_successful_code ["callable"]` + +Reports an error if the exit code of `callable` is not successful (`0`). + +If `callable` is not provided, it takes the last executed command or function instead. + +[assert_exit_code](#assert-exit-code) is the full version of this assertion where you can specify the expected exit code. + +::: code-group +```bash [Example] +function test_success_with_callable() { + function foo() { + return 0 + } + + assert_successful_code "$(foo)" +} + +function test_success_without_callable() { + function foo() { + return 0 + } + + foo # function took instead `callable` + + assert_successful_code +} + +function test_failure() { + function foo() { + return 1 + } + + assert_successful_code "$(foo)" +} +``` +::: + +## assert_general_error +> `assert_general_error ["callable"]` + +Reports an error if the exit code of `callable` is not a general error (`1`). + +If `callable` is not provided, it takes the last executed command or function instead. + +[assert_exit_code](#assert-exit-code) is the full version of this assertion where you can specify the expected exit code. + +::: code-group +```bash [Example] +function test_success_with_callable() { + function foo() { + return 1 + } + + assert_general_error "$(foo)" +} + +function test_success_without_callable() { + function foo() { + return 1 + } + + foo # function took instead `callable` + + assert_general_error +} + +function test_failure() { + function foo() { + return 0 + } + + assert_general_error "$(foo)" +} +``` +::: + +## assert_command_not_found +> `assert_general_error ["callable"]` + +Reports an error if `callable` exists. +In other words, if executing `callable` does not return a command not found exit code (`127`). + +If `callable` is not provided, it takes the last executed command or function instead. + +[assert_exit_code](#assert-exit-code) is the full version of this assertion where you can specify the expected exit code. + +::: code-group +```bash [Example] +function test_success_with_callable() { + assert_command_not_found "$(foo > /dev/null 2>&1)" +} + +function test_success_without_callable() { + foo > /dev/null 2>&1 + + assert_command_not_found +} + +function test_failure() { + assert_command_not_found "$(ls > /dev/null 2>&1)" +} +``` +::: + +## assert_file_exists +> `assert_file_exists "file"` + +Reports an error if `file` does not exists, or it is a directory. + +[assert_file_not_exists](#assert-file-not-exists) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + local file_path="foo.txt" + touch "$file_path" + + assert_file_exists "$file_path" + rm "$file_path" +} + +function test_failure() { + local file_path="foo.txt" + rm -f $file_path + + assert_file_exists "$file_path" +} +``` +::: + +## assert_file_contains +> `assert_file_contains "file" "search"` + +Reports an error if `file` does not contains the search string. + +[assert_file_not_contains](#assert-file-not-contains) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + local file="/tmp/file-path.txt" + echo -e "original content" > "$file" + + assert_file_contains "$file" "content" +} + +function test_failure() { + local file="/tmp/file-path.txt" + echo -e "original content" > "$file" + + assert_file_contains "$file" "non existing" +} +``` +::: + +## assert_is_file +> `assert_is_file "file"` + +Reports an error if `file` is not a file. + +::: code-group +```bash [Example] +function test_success() { + local file_path="foo.txt" + touch "$file_path" + + assert_is_file "$file_path" + rm "$file_path" +} + +function test_failure() { + local dir_path="bar" + mkdir "$dir_path" + + assert_is_file "$dir_path" + rmdir "$dir_path" +} +``` +::: + +## assert_is_file_empty +> `assert_is_file_empty "file"` + +Reports an error if `file` is not empty. + +::: code-group +```bash [Example] +function test_success() { + local file_path="foo.txt" + touch "$file_path" + + assert_is_file_empty "$file_path" + rm "$file_path" +} + +function test_failure() { + local file_path="foo.txt" + echo "bar" > "$file_path" + + assert_is_file_empty "$file_path" + rm "$file_path" +} +``` +::: + +## assert_directory_exists +> `assert_directory_exists "directory"` + +Reports an error if `directory` does not exist. + +[assert_directory_not_exists](#assert-directory-not-exists) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + local directory="/var" + + assert_directory_exists "$directory" +} + +function test_failure() { + local directory="/nonexistent_directory" + + assert_directory_exists "$directory" +} +``` +::: + +## assert_is_directory +> `assert_is_directory "directory"` + +Reports an error if `directory` is not a directory. + +::: code-group +```bash [Example] +function test_success() { + local directory="/var" + + assert_is_directory "$directory" +} + +function test_failure() { + local file="/etc/hosts" + + assert_is_directory "$file" +} +``` +::: + +## assert_is_directory_empty +> `assert_is_directory_empty "directory"` + +Reports an error if `directory` is not an empty directory. + +[assert_is_directory_not_empty](#assert-is-directory-not-empty) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + local directory="/home/user/empty_directory" + mkdir "$directory" + + assert_is_directory_empty "$directory" +} + +function test_failure() { + local directory="/etc" + + assert_is_directory_empty "$directory" +} +``` +::: + +## assert_is_directory_readable +> `assert_is_directory_readable "directory"` + +Reports an error if `directory` is not a readable directory. + +[assert_is_directory_not_readable](#assert-is-directory-not-readable) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + local directory="/var" + + assert_is_directory_readable "$directory" +} + +function test_failure() { + local directory="/home/user/test" + chmod -r "$directory" + + assert_is_directory_readable "$directory" +} +``` +::: + +## assert_is_directory_writable +> `assert_is_directory_writable "directory"` + +Reports an error if `directory` is not a writable directory. + +[assert_is_directory_not_writable](#assert-is-directory-not-writable) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + local directory="/tmp" + + assert_is_directory_writable "$directory" +} + +function test_failure() { + local directory="/home/user/test" + chmod -w "$directory" + + assert_is_directory_writable "$directory" +} +``` +::: + +## assert_files_equals +> `assert_files_equals "expected" "actual"` + +Reports an error if `expected` and `actual` are not equals. + +[assert_files_not_equals](#assert-files-not-equals) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + local expected="/tmp/file1.txt" + local actual="/tmp/file2.txt" + + echo "file content" > "$expected" + echo "file content" > "$actual" + + assert_files_equals "$expected" "$actual" +} + +function test_failure() { + local expected="/tmp/file1.txt" + local actual="/tmp/file2.txt" + + echo "file content" > "$expected" + echo "different content" > "$actual" + + assert_files_equals "$expected" "$actual" +} +``` +```[Output] +✓ Passed: Success +✗ Failed: Failure + Expected '/tmp/file1.txt' + Compared '/tmp/file2.txt' + Diff '@@ -1 +1 @@ +-file content ++different content' +``` +::: + +## assert_not_same +> `assert_not_same "expected" "actual"` + +Reports an error if the two variables `expected` and `actual` are the same value. + +[assert_same](#assert-same) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + assert_not_same "foo" "bar" +} + +function test_failure() { + assert_not_same "foo" "foo" +} +``` +::: + +## assert_not_contains +> `assert_not_contains "needle" "haystack"` + +Reports an error if `needle` is a substring of `haystack`. + +[assert_contains](#assert-contains) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + assert_not_contains "baz" "foobar" +} + +function test_failure() { + assert_not_contains "foo" "foobar" +} +``` +::: + +## assert_string_not_starts_with +> `assert_string_not_starts_with "needle" "haystack"` + +Reports an error if `haystack` does starts with `needle`. + +[assert_string_starts_with](#assert-string-starts-with) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + assert_string_not_starts_with "bar" "foobar" +} + +function test_failure() { + assert_string_not_starts_with "foo" "foobar" +} +``` +::: + +## assert_string_not_ends_with +> `assert_string_not_ends_with "needle" "haystack"` + +Reports an error if `haystack` does ends with `needle`. + +[assert_string_ends_with](#assert-string-ends-with) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + assert_string_not_ends_with "foo" "foobar" +} + +function test_failure() { + assert_string_not_ends_with "bar" "foobar" +} +``` +::: + +## assert_not_empty +> `assert_not_empty "actual"` + +Reports an error if `actual` is empty. + +[assert_empty](#assert-empty) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + assert_not_empty "foo" +} + +function test_failure() { + assert_not_empty "" +} +``` +::: + +## assert_not_matches +> `assert_not_matches "pattern" "value"` + +Reports an error if `value` matches the regular expression `pattern`. + +[assert_matches](#assert-matches) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + assert_not_matches "foo$" "foobar" +} + +function test_failure() { + assert_not_matches "bar$" "foobar" +} +``` +::: + +## assert_array_not_contains +> `assert_array_not_contains "needle" "haystack"` + +Reports an error if `needle` is an element of `haystack`. + +[assert_array_contains](#assert-array-contains) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + local haystack=(foo bar baz) + + assert_array_not_contains "foobar" "${haystack[@]}" +} + +function test_failure() { + local haystack=(foo bar baz) + + assert_array_not_contains "baz" "${haystack[@]}" +} +``` +::: + +## assert_file_not_exists +> `assert_file_not_exists "file"` + +Reports an error if `file` does exists. + +[assert_file_exists](#assert-file-exists) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + local file_path="foo.txt" + touch "$file_path" + rm "$file_path" + + assert_file_not_exists "$file_path" +} + +function test_failed() { + local file_path="foo.txt" + touch "$file_path" + + assert_file_not_exists "$file_path" + rm "$file_path" +} +``` +::: + +## assert_file_not_contains +> `assert_file_not_contains "file" "search"` + +Reports an error if `file` contains the search string. + +[assert_file_contains](#assert-file-contains) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + local file="/tmp/file-path.txt" + echo -e "original content" > "$file" + + assert_file_not_contains "$file" "non existing" +} + +function test_failure() { + local file="/tmp/file-path.txt" + echo -e "original content" > "$file" + + assert_file_not_contains "$file" "content" +} +``` +::: + +## assert_directory_not_exists +> `assert_directory_not_exists "directory"` + +Reports an error if `directory` exists. + +[assert_directory_exists](#assert-directory-exists) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + local directory="/nonexistent_directory" + + assert_directory_not_exists "$directory" +} + +function test_failure() { + local directory="/var" + + assert_directory_not_exists "$directory" +} +``` +::: + +## assert_is_directory_not_empty +> `assert_is_directory_not_empty "directory"` + +Reports an error if `directory` is empty. + +[assert_is_directory_empty](#assert-is-directory-empty) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + local directory="/etc" + + assert_is_directory_not_empty "$directory" +} + +function test_failure() { + local directory="/home/user/empty_directory" + mkdir "$directory" + + assert_is_directory_not_empty "$directory" +} +``` +::: + +## assert_is_directory_not_readable +> `assert_is_directory_not_readable "directory"` + +Reports an error if `directory` is readable. + +[assert_is_directory_readable](#assert-is-directory-readable) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + local directory="/home/user/test" + chmod -r "$directory" + + assert_is_directory_not_readable "$directory" +} + +function test_failure() { + local directory="/var" + + assert_is_directory_not_readable "$directory" +} +``` +::: + +## assert_is_directory_not_writable +> `assert_is_directory_not_writable "directory"` + +Reports an error if `directory` is writable. + +[assert_is_directory_writable](#assert-is-directory-writable) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + local directory="/home/user/test" + chmod -w "$directory" + + assert_is_directory_not_writable "$directory" +} + +function test_failure() { + local directory="/tmp" + + assert_is_directory_not_writable "$directory" +} +``` +::: + + +## assert_files_not_equals +> `assert_files_not_equals "expected" "actual"` + +Reports an error if `expected` and `actual` are not equals. + +[assert_files_equals](#assert-files-equals) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + local expected="/tmp/file1.txt" + local actual="/tmp/file2.txt" + + echo "file content" > "$expected" + echo "different content" > "$actual" + + assert_files_not_equals "$expected" "$actual" +} + +function test_failure() { + + local expected="/tmp/file1.txt" + local actual="/tmp/file2.txt" + + echo "file content" > "$expected" + echo "file content" > "$actual" + + assert_files_not_equals "$expected" "$actual" +} +``` +```[Output] +✓ Passed: Success +✗ Failed: Failure + Expected '/tmp/file1.txt' + Compared '/tmp/file2.txt' + Diff 'Files are equals' +``` +::: + +## fail +> `fail "failure message"` + +Unambiguously reports an error message. Useful for reporting specific message +when testing situations not covered by any `assert_*` functions. + +::: code-group +```bash [Example] +function test_success() { + if [ "$(date +%-H)" -gt 25 ]; then + fail "Something is very wrong with your clock" + fi +} +function test_failure() { + if [ "$(date +%-H)" -lt 25 ]; then + fail "This test will always fail" + fi +} +``` +::: diff --git a/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_filtered_assert_docs.snapshot b/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_filtered_assert_docs.snapshot new file mode 100644 index 00000000..e0a36bd6 --- /dev/null +++ b/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_filtered_assert_docs.snapshot @@ -0,0 +1,118 @@ +## assert_equals +> `assert_equals "expected" "actual"` + +Reports an error if the two variables `expected` and `actual` are not equal ignoring the special chars like ANSI Escape Sequences (colors) and other special chars like tabs and new lines. + +- [assert_same](#assert-same) is similar but including special chars. + +::: code-group +```bash [Example] +function test_success() { + assert_equals "foo" "\e[31mfoo" +} + +function test_failure() { + assert_equals "\e[31mfoo" "\e[31mfoo" +} +``` +::: + +## assert_files_equals +> `assert_files_equals "expected" "actual"` + +Reports an error if `expected` and `actual` are not equals. + +[assert_files_not_equals](#assert-files-not-equals) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + local expected="/tmp/file1.txt" + local actual="/tmp/file2.txt" + + echo "file content" > "$expected" + echo "file content" > "$actual" + + assert_files_equals "$expected" "$actual" +} + +function test_failure() { + local expected="/tmp/file1.txt" + local actual="/tmp/file2.txt" + + echo "file content" > "$expected" + echo "different content" > "$actual" + + assert_files_equals "$expected" "$actual" +} +``` +```[Output] +✓ Passed: Success +✗ Failed: Failure + Expected '/tmp/file1.txt' + Compared '/tmp/file2.txt' + Diff '@@ -1 +1 @@ +-file content ++different content' +``` +::: + +## assert_files_not_equals +> `assert_files_not_equals "expected" "actual"` + +Reports an error if `expected` and `actual` are not equals. + +[assert_files_equals](#assert-files-equals) is the inverse of this assertion and takes the same arguments. + +::: code-group +```bash [Example] +function test_success() { + local expected="/tmp/file1.txt" + local actual="/tmp/file2.txt" + + echo "file content" > "$expected" + echo "different content" > "$actual" + + assert_files_not_equals "$expected" "$actual" +} + +function test_failure() { + + local expected="/tmp/file1.txt" + local actual="/tmp/file2.txt" + + echo "file content" > "$expected" + echo "file content" > "$actual" + + assert_files_not_equals "$expected" "$actual" +} +``` +```[Output] +✓ Passed: Success +✗ Failed: Failure + Expected '/tmp/file1.txt' + Compared '/tmp/file2.txt' + Diff 'Files are equals' +``` +::: + +## fail +> `fail "failure message"` + +Unambiguously reports an error message. Useful for reporting specific message +when testing situations not covered by any `assert_*` functions. + +::: code-group +```bash [Example] +function test_success() { + if [ "$(date +%-H)" -gt 25 ]; then + fail "Something is very wrong with your clock" + fi +} +function test_failure() { + if [ "$(date +%-H)" -lt 25 ]; then + fail "This test will always fail" + fi +} +``` +::: diff --git a/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_help.snapshot b/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_help.snapshot index af2e750b..aee3bb79 100644 --- a/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_help.snapshot +++ b/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_help.snapshot @@ -27,6 +27,10 @@ Options: -h, --help Show this help message. + --doc + Display the documentation for assert functions. When a filter is + provided, only matching asserts will be shown. + --init [dir] Generate a sample test suite in current or specified directory. From f7216c84c50d9ca287089284d7809925e3cd9030 Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Sun, 20 Jul 2025 13:00:45 +0200 Subject: [PATCH 02/10] docs: update assertions.md --- docs/assertions.md | 70 +++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/docs/assertions.md b/docs/assertions.md index a9cdcdd9..139ae990 100644 --- a/docs/assertions.md +++ b/docs/assertions.md @@ -113,7 +113,7 @@ function test_failure() { Reports an error if `needle` is not a substring of `haystack`. -[assert_not_contains](#assert-not-contains) is the inverse of this assertion and takes the same arguments. +- [assert_not_contains](#assert-not-contains) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -150,7 +150,7 @@ function test_failure() { Reports an error if `actual` is not empty. -[assert_not_empty](#assert-not-empty) is the inverse of this assertion and takes the same arguments. +- [assert_not_empty](#assert-not-empty) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -169,7 +169,7 @@ function test_failure() { Reports an error if `value` does not match the regular expression `pattern`. -[assert_not_matches](#assert-not-matches) is the inverse of this assertion and takes the same arguments. +- [assert_not_matches](#assert-not-matches) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -188,7 +188,7 @@ function test_failure() { Reports an error if `haystack` does not starts with `needle`. -[assert_string_not_starts_with](#assert-string-not-starts-with) is the inverse of this assertion and takes the same arguments. +- [assert_string_not_starts_with](#assert-string-not-starts-with) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -207,7 +207,7 @@ function test_failure() { Reports an error if `haystack` does not ends with `needle`. -[assert_string_not_ends_with](#assert-string-not-ends-with) is the inverse of this assertion and takes the same arguments. +- [assert_string_not_ends_with](#assert-string-not-ends-with) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -247,7 +247,7 @@ function test_failure() { Reports an error if `actual` is not less than `expected`. -[assert_greater_than](#assert-greater-than) is the inverse of this assertion and takes the same arguments. +- [assert_greater_than](#assert-greater-than) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -266,7 +266,7 @@ function test_failure() { Reports an error if `actual` is not less than or equal to `expected`. -[assert_greater_than](#assert-greater-or-equal-than) is the inverse of this assertion and takes the same arguments. +- [assert_greater_than](#assert-greater-or-equal-than) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -289,7 +289,7 @@ function test_failure() { Reports an error if `actual` is not greater than `expected`. -[assert_less_than](#assert-less-than) is the inverse of this assertion and takes the same arguments. +- [assert_less_than](#assert-less-than) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -308,7 +308,7 @@ function test_failure() { Reports an error if `actual` is not greater than or equal to `expected`. -[assert_less_or_equal_than](#assert-less-or-equal-than) is the inverse of this assertion and takes the same arguments. +- [assert_less_or_equal_than](#assert-less-or-equal-than) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -333,7 +333,7 @@ Reports an error if the exit code of `callable` is not equal to `expected`. If `callable` is not provided, it takes the last executed command or function instead. -[assert_successful_code](#assert-successful-code), [assert_general_error](#assert-general-error) and [assert_command_not_found](#assert-command-not-found) +- [assert_successful_code](#assert-successful-code), [assert_general_error](#assert-general-error) and [assert_command_not_found](#assert-command-not-found) are more semantic versions of this assertion, for which you don't need to specify an exit code. ::: code-group @@ -371,7 +371,7 @@ function test_failure() { Reports an error if `needle` is not an element of `haystack`. -[assert_array_not_contains](#assert-array-not-contains) is the inverse of this assertion and takes the same arguments. +- [assert_array_not_contains](#assert-array-not-contains) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -396,7 +396,7 @@ Reports an error if the exit code of `callable` is not successful (`0`). If `callable` is not provided, it takes the last executed command or function instead. -[assert_exit_code](#assert-exit-code) is the full version of this assertion where you can specify the expected exit code. +- [assert_exit_code](#assert-exit-code) is the full version of this assertion where you can specify the expected exit code. ::: code-group ```bash [Example] @@ -435,7 +435,7 @@ Reports an error if the exit code of `callable` is not a general error (`1`). If `callable` is not provided, it takes the last executed command or function instead. -[assert_exit_code](#assert-exit-code) is the full version of this assertion where you can specify the expected exit code. +- [assert_exit_code](#assert-exit-code) is the full version of this assertion where you can specify the expected exit code. ::: code-group ```bash [Example] @@ -475,7 +475,7 @@ In other words, if executing `callable` does not return a command not found exit If `callable` is not provided, it takes the last executed command or function instead. -[assert_exit_code](#assert-exit-code) is the full version of this assertion where you can specify the expected exit code. +- [assert_exit_code](#assert-exit-code) is the full version of this assertion where you can specify the expected exit code. ::: code-group ```bash [Example] @@ -500,7 +500,7 @@ function test_failure() { Reports an error if `file` does not exists, or it is a directory. -[assert_file_not_exists](#assert-file-not-exists) is the inverse of this assertion and takes the same arguments. +- [assert_file_not_exists](#assert-file-not-exists) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -526,7 +526,7 @@ function test_failure() { Reports an error if `file` does not contains the search string. -[assert_file_not_contains](#assert-file-not-contains) is the inverse of this assertion and takes the same arguments. +- [assert_file_not_contains](#assert-file-not-contains) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -601,7 +601,7 @@ function test_failure() { Reports an error if `directory` does not exist. -[assert_directory_not_exists](#assert-directory-not-exists) is the inverse of this assertion and takes the same arguments. +- [assert_directory_not_exists](#assert-directory-not-exists) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -645,7 +645,7 @@ function test_failure() { Reports an error if `directory` is not an empty directory. -[assert_is_directory_not_empty](#assert-is-directory-not-empty) is the inverse of this assertion and takes the same arguments. +- [assert_is_directory_not_empty](#assert-is-directory-not-empty) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -669,7 +669,7 @@ function test_failure() { Reports an error if `directory` is not a readable directory. -[assert_is_directory_not_readable](#assert-is-directory-not-readable) is the inverse of this assertion and takes the same arguments. +- [assert_is_directory_not_readable](#assert-is-directory-not-readable) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -693,7 +693,7 @@ function test_failure() { Reports an error if `directory` is not a writable directory. -[assert_is_directory_not_writable](#assert-is-directory-not-writable) is the inverse of this assertion and takes the same arguments. +- [assert_is_directory_not_writable](#assert-is-directory-not-writable) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -717,7 +717,7 @@ function test_failure() { Reports an error if `expected` and `actual` are not equals. -[assert_files_not_equals](#assert-files-not-equals) is the inverse of this assertion and takes the same arguments. +- [assert_files_not_equals](#assert-files-not-equals) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -757,7 +757,7 @@ function test_failure() { Reports an error if the two variables `expected` and `actual` are the same value. -[assert_same](#assert-same) is the inverse of this assertion and takes the same arguments. +- [assert_same](#assert-same) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -776,7 +776,7 @@ function test_failure() { Reports an error if `needle` is a substring of `haystack`. -[assert_contains](#assert-contains) is the inverse of this assertion and takes the same arguments. +- [assert_contains](#assert-contains) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -795,7 +795,7 @@ function test_failure() { Reports an error if `haystack` does starts with `needle`. -[assert_string_starts_with](#assert-string-starts-with) is the inverse of this assertion and takes the same arguments. +- [assert_string_starts_with](#assert-string-starts-with) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -814,7 +814,7 @@ function test_failure() { Reports an error if `haystack` does ends with `needle`. -[assert_string_ends_with](#assert-string-ends-with) is the inverse of this assertion and takes the same arguments. +- [assert_string_ends_with](#assert-string-ends-with) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -833,7 +833,7 @@ function test_failure() { Reports an error if `actual` is empty. -[assert_empty](#assert-empty) is the inverse of this assertion and takes the same arguments. +- [assert_empty](#assert-empty) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -852,7 +852,7 @@ function test_failure() { Reports an error if `value` matches the regular expression `pattern`. -[assert_matches](#assert-matches) is the inverse of this assertion and takes the same arguments. +- [assert_matches](#assert-matches) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -871,7 +871,7 @@ function test_failure() { Reports an error if `needle` is an element of `haystack`. -[assert_array_contains](#assert-array-contains) is the inverse of this assertion and takes the same arguments. +- [assert_array_contains](#assert-array-contains) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -894,7 +894,7 @@ function test_failure() { Reports an error if `file` does exists. -[assert_file_exists](#assert-file-exists) is the inverse of this assertion and takes the same arguments. +- [assert_file_exists](#assert-file-exists) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -921,7 +921,7 @@ function test_failed() { Reports an error if `file` contains the search string. -[assert_file_contains](#assert-file-contains) is the inverse of this assertion and takes the same arguments. +- [assert_file_contains](#assert-file-contains) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -946,7 +946,7 @@ function test_failure() { Reports an error if `directory` exists. -[assert_directory_exists](#assert-directory-exists) is the inverse of this assertion and takes the same arguments. +- [assert_directory_exists](#assert-directory-exists) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -969,7 +969,7 @@ function test_failure() { Reports an error if `directory` is empty. -[assert_is_directory_empty](#assert-is-directory-empty) is the inverse of this assertion and takes the same arguments. +- [assert_is_directory_empty](#assert-is-directory-empty) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -993,7 +993,7 @@ function test_failure() { Reports an error if `directory` is readable. -[assert_is_directory_readable](#assert-is-directory-readable) is the inverse of this assertion and takes the same arguments. +- [assert_is_directory_readable](#assert-is-directory-readable) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -1017,7 +1017,7 @@ function test_failure() { Reports an error if `directory` is writable. -[assert_is_directory_writable](#assert-is-directory-writable) is the inverse of this assertion and takes the same arguments. +- [assert_is_directory_writable](#assert-is-directory-writable) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] @@ -1042,7 +1042,7 @@ function test_failure() { Reports an error if `expected` and `actual` are not equals. -[assert_files_equals](#assert-files-equals) is the inverse of this assertion and takes the same arguments. +- [assert_files_equals](#assert-files-equals) is the inverse of this assertion and takes the same arguments. ::: code-group ```bash [Example] From 987a69367bd8b38f5d68d8c7f5cd5d74d295e787 Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Sun, 20 Jul 2025 13:25:16 +0200 Subject: [PATCH 03/10] chore: improve style of print_asserts --- src/doc.sh | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/doc.sh b/src/doc.sh index d824191d..10c28759 100644 --- a/src/doc.sh +++ b/src/doc.sh @@ -5,19 +5,31 @@ function doc::print_asserts() { local doc_file="$BASHUNIT_ROOT_DIR/docs/assertions.md" local line local print=0 + local docstring="" while IFS='' read -r line || [[ -n "$line" ]]; do if [[ $line =~ ^##\ (assert_[A-Za-z0-9_]+) ]]; then local fn="${BASH_REMATCH[1]}" if [[ -z "$search" || "$fn" == *"$search"* ]]; then print=1 echo "$line" + docstring="" else print=0 fi continue fi + if [[ $print -eq 1 ]]; then - echo "$line" + if [[ "$line" =~ ^\`\`\` ]]; then + print=0 + echo "--------------" + echo "$docstring" + continue + fi + [[ "$line" == "::: code-group" ]] && continue + line="${line//[\[\]]/}" + line="$(sed -E 's/ *\(#[-a-z0-9]+\)//g' <<< "$line")" + docstring+="$line"$'\n' fi done < "$doc_file" } From f510803e338e527c3e5d9a83d54c0af00072f4b2 Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Sun, 20 Jul 2025 13:41:26 +0200 Subject: [PATCH 04/10] fix: snapshot docs --- ...it_should_display_all_assert_docs.snapshot | 878 ++---------------- ...ould_display_filtered_assert_docs.snapshot | 105 +-- 2 files changed, 97 insertions(+), 886 deletions(-) diff --git a/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_all_assert_docs.snapshot b/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_all_assert_docs.snapshot index 41e06605..09416ee8 100644 --- a/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_all_assert_docs.snapshot +++ b/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_all_assert_docs.snapshot @@ -1,1092 +1,396 @@ ## assert_true +-------------- > `assert_true bool|function|command` Reports an error if the argument result in a truthy value: `true` or `0`. -- [assert_false](#assert-false) is similar but different. - -::: code-group -```bash [Example] -function test_success() { - assert_true true - assert_true 0 - assert_true "eval return 0" - assert_true mock_true -} - -function test_failure() { - assert_true false - assert_true 1 - assert_true "eval return 1" - assert_true mock_false -} -``` -```bash [globals.sh] -function mock_true() { - return 0 -} -function mock_false() { - return 1 -} -::: +- assert_false is similar but different. + ## assert_false +-------------- > `assert_false bool|function|command` Reports an error if the argument result in a falsy value: `false` or `1`. -- [assert_true](#assert-true) is similar but different. - -::: code-group -```bash [Example] -function test_success() { - assert_false false - assert_false 1 - assert_false "eval return 1" - assert_false mock_false -} - -function test_failure() { - assert_false true - assert_false 0 - assert_false "eval return 0" - assert_false mock_true -} -``` -```bash [globals.sh] -function mock_true() { - return 0 -} -function mock_false() { - return 1 -} -``` -::: +- assert_true is similar but different. + ## assert_same +-------------- > `assert_same "expected" "actual"` Reports an error if the `expected` and `actual` are not the same - including special chars. -- [assert_not_same](#assert-not-same) is the inverse of this assertion and takes the same arguments. -- [assert_equals](#assert-equals) is similar but ignoring the special chars. +- assert_not_same is the inverse of this assertion and takes the same arguments. +- assert_equals is similar but ignoring the special chars. -::: code-group -```bash [Example] -function test_success() { - assert_same "foo" "foo" -} - -function test_failure() { - assert_same "foo" "bar" -} -``` -::: ## assert_equals +-------------- > `assert_equals "expected" "actual"` Reports an error if the two variables `expected` and `actual` are not equal ignoring the special chars like ANSI Escape Sequences (colors) and other special chars like tabs and new lines. -- [assert_same](#assert-same) is similar but including special chars. - -::: code-group -```bash [Example] -function test_success() { - assert_equals "foo" "\e[31mfoo" -} +- assert_same is similar but including special chars. -function test_failure() { - assert_equals "\e[31mfoo" "\e[31mfoo" -} -``` -::: ## assert_contains +-------------- > `assert_contains "needle" "haystack"` Reports an error if `needle` is not a substring of `haystack`. -[assert_not_contains](#assert-not-contains) is the inverse of this assertion and takes the same arguments. +- assert_not_contains is the inverse of this assertion and takes the same arguments. -::: code-group -```bash [Example] -function test_success() { - assert_contains "foo" "foobar" -} - -function test_failure() { - assert_contains "baz" "foobar" -} -``` - -::: ## assert_contains_ignore_case +-------------- > `assert_contains_ignore_case "needle" "haystack"` Reports an error if `needle` is not a substring of `haystack`. Differences in casing are ignored when needle is searched for in haystack. -::: code-group -```bash [Example] -function test_success() { - assert_contains_ignore_case "foo" "FooBar" -} -function test_failure() { - assert_contains_ignore_case "baz" "FooBar" -} -``` -::: ## assert_empty +-------------- > `assert_empty "actual"` Reports an error if `actual` is not empty. -[assert_not_empty](#assert-not-empty) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - assert_empty "" -} +- assert_not_empty is the inverse of this assertion and takes the same arguments. -function test_failure() { - assert_empty "foo" -} -``` -::: ## assert_matches +-------------- > `assert_matches "pattern" "value"` Reports an error if `value` does not match the regular expression `pattern`. -[assert_not_matches](#assert-not-matches) is the inverse of this assertion and takes the same arguments. +- assert_not_matches is the inverse of this assertion and takes the same arguments. -::: code-group -```bash [Example] -function test_success() { - assert_matches "^foo" "foobar" -} - -function test_failure() { - assert_matches "^bar" "foobar" -} -``` -::: ## assert_string_starts_with +-------------- > `assert_string_starts_with "needle" "haystack"` Reports an error if `haystack` does not starts with `needle`. -[assert_string_not_starts_with](#assert-string-not-starts-with) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - assert_string_starts_with "foo" "foobar" -} +- assert_string_not_starts_with is the inverse of this assertion and takes the same arguments. -function test_failure() { - assert_string_starts_with "baz" "foobar" -} -``` -::: ## assert_string_ends_with +-------------- > `assert_string_ends_with "needle" "haystack"` Reports an error if `haystack` does not ends with `needle`. -[assert_string_not_ends_with](#assert-string-not-ends-with) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - assert_string_ends_with "bar" "foobar" -} +- assert_string_not_ends_with is the inverse of this assertion and takes the same arguments. -function test_failure() { - assert_string_ends_with "foo" "foobar" -} -``` -::: ## assert_line_count +-------------- > `assert_line_count "count" "haystack"` Reports an error if `haystack` does not contain `count` lines. -::: code-group -```bash [Example] -function test_success() { - local string="this is line one -this is line two -this is line three" - - assert_line_count 3 "$string" -} - -function test_failure() { - assert_line_count 2 "foobar" -} -``` -::: ## assert_less_than +-------------- > `assert_less_than "expected" "actual"` Reports an error if `actual` is not less than `expected`. -[assert_greater_than](#assert-greater-than) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - assert_less_than "999" "1" -} +- assert_greater_than is the inverse of this assertion and takes the same arguments. -function test_failure() { - assert_less_than "1" "999" -} -``` -::: ## assert_less_or_equal_than +-------------- > `assert_less_or_equal_than "expected" "actual"` Reports an error if `actual` is not less than or equal to `expected`. -[assert_greater_than](#assert-greater-or-equal-than) is the inverse of this assertion and takes the same arguments. +- assert_greater_than is the inverse of this assertion and takes the same arguments. -::: code-group -```bash [Example] -function test_success() { - assert_less_or_equal_than "999" "1" -} - -function test_success_with_two_equal_numbers() { - assert_less_or_equal_than "999" "999" -} - -function test_failure() { - assert_less_or_equal_than "1" "999" -} -``` -::: ## assert_greater_than +-------------- > `assert_greater_than "expected" "actual"` Reports an error if `actual` is not greater than `expected`. -[assert_less_than](#assert-less-than) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - assert_greater_than "1" "999" -} +- assert_less_than is the inverse of this assertion and takes the same arguments. -function test_failure() { - assert_greater_than "999" "1" -} -``` -::: ## assert_greater_or_equal_than +-------------- > `assert_greater_or_equal_than "expected" "actual"` Reports an error if `actual` is not greater than or equal to `expected`. -[assert_less_or_equal_than](#assert-less-or-equal-than) is the inverse of this assertion and takes the same arguments. +- assert_less_or_equal_than is the inverse of this assertion and takes the same arguments. -::: code-group -```bash [Example] -function test_success() { - assert_greater_or_equal_than "1" "999" -} - -function test_success_with_two_equal_numbers() { - assert_greater_or_equal_than "999" "999" -} - -function test_failure() { - assert_greater_or_equal_than "999" "1" -} -``` -::: ## assert_exit_code -> `assert_exit_code "expected" ["callable"]` +-------------- +> `assert_exit_code "expected" "callable"` Reports an error if the exit code of `callable` is not equal to `expected`. If `callable` is not provided, it takes the last executed command or function instead. -[assert_successful_code](#assert-successful-code), [assert_general_error](#assert-general-error) and [assert_command_not_found](#assert-command-not-found) +- assert_successful_code, assert_general_error and assert_command_not_found are more semantic versions of this assertion, for which you don't need to specify an exit code. -::: code-group -```bash [Example] -function test_success_with_callable() { - function foo() { - return 1 - } - - assert_exit_code "1" "$(foo)" -} - -function test_success_without_callable() { - function foo() { - return 1 - } - - foo # function took instead `callable` - - assert_exit_code "1" -} - -function test_failure() { - function foo() { - return 1 - } - - assert_exit_code "0" "$(foo)" -} -``` -::: ## assert_array_contains +-------------- > `assert_array_contains "needle" "haystack"` Reports an error if `needle` is not an element of `haystack`. -[assert_array_not_contains](#assert-array-not-contains) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - local haystack=(foo bar baz) +- assert_array_not_contains is the inverse of this assertion and takes the same arguments. - assert_array_contains "bar" "${haystack[@]}" -} - -function test_failure() { - local haystack=(foo bar baz) - - assert_array_contains "foobar" "${haystack[@]}" -} -``` -::: ## assert_successful_code -> `assert_successful_code ["callable"]` +-------------- +> `assert_successful_code "callable"` Reports an error if the exit code of `callable` is not successful (`0`). If `callable` is not provided, it takes the last executed command or function instead. -[assert_exit_code](#assert-exit-code) is the full version of this assertion where you can specify the expected exit code. - -::: code-group -```bash [Example] -function test_success_with_callable() { - function foo() { - return 0 - } - - assert_successful_code "$(foo)" -} - -function test_success_without_callable() { - function foo() { - return 0 - } - - foo # function took instead `callable` +- assert_exit_code is the full version of this assertion where you can specify the expected exit code. - assert_successful_code -} - -function test_failure() { - function foo() { - return 1 - } - - assert_successful_code "$(foo)" -} -``` -::: ## assert_general_error -> `assert_general_error ["callable"]` +-------------- +> `assert_general_error "callable"` Reports an error if the exit code of `callable` is not a general error (`1`). If `callable` is not provided, it takes the last executed command or function instead. -[assert_exit_code](#assert-exit-code) is the full version of this assertion where you can specify the expected exit code. - -::: code-group -```bash [Example] -function test_success_with_callable() { - function foo() { - return 1 - } - - assert_general_error "$(foo)" -} - -function test_success_without_callable() { - function foo() { - return 1 - } - - foo # function took instead `callable` +- assert_exit_code is the full version of this assertion where you can specify the expected exit code. - assert_general_error -} - -function test_failure() { - function foo() { - return 0 - } - - assert_general_error "$(foo)" -} -``` -::: ## assert_command_not_found -> `assert_general_error ["callable"]` +-------------- +> `assert_general_error "callable"` Reports an error if `callable` exists. In other words, if executing `callable` does not return a command not found exit code (`127`). If `callable` is not provided, it takes the last executed command or function instead. -[assert_exit_code](#assert-exit-code) is the full version of this assertion where you can specify the expected exit code. - -::: code-group -```bash [Example] -function test_success_with_callable() { - assert_command_not_found "$(foo > /dev/null 2>&1)" -} +- assert_exit_code is the full version of this assertion where you can specify the expected exit code. -function test_success_without_callable() { - foo > /dev/null 2>&1 - - assert_command_not_found -} - -function test_failure() { - assert_command_not_found "$(ls > /dev/null 2>&1)" -} -``` -::: ## assert_file_exists +-------------- > `assert_file_exists "file"` Reports an error if `file` does not exists, or it is a directory. -[assert_file_not_exists](#assert-file-not-exists) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - local file_path="foo.txt" - touch "$file_path" +- assert_file_not_exists is the inverse of this assertion and takes the same arguments. - assert_file_exists "$file_path" - rm "$file_path" -} - -function test_failure() { - local file_path="foo.txt" - rm -f $file_path - - assert_file_exists "$file_path" -} -``` -::: ## assert_file_contains +-------------- > `assert_file_contains "file" "search"` Reports an error if `file` does not contains the search string. -[assert_file_not_contains](#assert-file-not-contains) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - local file="/tmp/file-path.txt" - echo -e "original content" > "$file" +- assert_file_not_contains is the inverse of this assertion and takes the same arguments. - assert_file_contains "$file" "content" -} - -function test_failure() { - local file="/tmp/file-path.txt" - echo -e "original content" > "$file" - - assert_file_contains "$file" "non existing" -} -``` -::: ## assert_is_file +-------------- > `assert_is_file "file"` Reports an error if `file` is not a file. -::: code-group -```bash [Example] -function test_success() { - local file_path="foo.txt" - touch "$file_path" - - assert_is_file "$file_path" - rm "$file_path" -} - -function test_failure() { - local dir_path="bar" - mkdir "$dir_path" - - assert_is_file "$dir_path" - rmdir "$dir_path" -} -``` -::: ## assert_is_file_empty +-------------- > `assert_is_file_empty "file"` Reports an error if `file` is not empty. -::: code-group -```bash [Example] -function test_success() { - local file_path="foo.txt" - touch "$file_path" - - assert_is_file_empty "$file_path" - rm "$file_path" -} - -function test_failure() { - local file_path="foo.txt" - echo "bar" > "$file_path" - - assert_is_file_empty "$file_path" - rm "$file_path" -} -``` -::: ## assert_directory_exists +-------------- > `assert_directory_exists "directory"` Reports an error if `directory` does not exist. -[assert_directory_not_exists](#assert-directory-not-exists) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - local directory="/var" - - assert_directory_exists "$directory" -} +- assert_directory_not_exists is the inverse of this assertion and takes the same arguments. -function test_failure() { - local directory="/nonexistent_directory" - - assert_directory_exists "$directory" -} -``` -::: ## assert_is_directory +-------------- > `assert_is_directory "directory"` Reports an error if `directory` is not a directory. -::: code-group -```bash [Example] -function test_success() { - local directory="/var" - - assert_is_directory "$directory" -} - -function test_failure() { - local file="/etc/hosts" - - assert_is_directory "$file" -} -``` -::: ## assert_is_directory_empty +-------------- > `assert_is_directory_empty "directory"` Reports an error if `directory` is not an empty directory. -[assert_is_directory_not_empty](#assert-is-directory-not-empty) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - local directory="/home/user/empty_directory" - mkdir "$directory" - - assert_is_directory_empty "$directory" -} +- assert_is_directory_not_empty is the inverse of this assertion and takes the same arguments. -function test_failure() { - local directory="/etc" - - assert_is_directory_empty "$directory" -} -``` -::: ## assert_is_directory_readable +-------------- > `assert_is_directory_readable "directory"` Reports an error if `directory` is not a readable directory. -[assert_is_directory_not_readable](#assert-is-directory-not-readable) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - local directory="/var" - - assert_is_directory_readable "$directory" -} +- assert_is_directory_not_readable is the inverse of this assertion and takes the same arguments. -function test_failure() { - local directory="/home/user/test" - chmod -r "$directory" - - assert_is_directory_readable "$directory" -} -``` -::: ## assert_is_directory_writable +-------------- > `assert_is_directory_writable "directory"` Reports an error if `directory` is not a writable directory. -[assert_is_directory_not_writable](#assert-is-directory-not-writable) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - local directory="/tmp" - - assert_is_directory_writable "$directory" -} +- assert_is_directory_not_writable is the inverse of this assertion and takes the same arguments. -function test_failure() { - local directory="/home/user/test" - chmod -w "$directory" - - assert_is_directory_writable "$directory" -} -``` -::: ## assert_files_equals +-------------- > `assert_files_equals "expected" "actual"` Reports an error if `expected` and `actual` are not equals. -[assert_files_not_equals](#assert-files-not-equals) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - local expected="/tmp/file1.txt" - local actual="/tmp/file2.txt" - - echo "file content" > "$expected" - echo "file content" > "$actual" - - assert_files_equals "$expected" "$actual" -} - -function test_failure() { - local expected="/tmp/file1.txt" - local actual="/tmp/file2.txt" - - echo "file content" > "$expected" - echo "different content" > "$actual" - - assert_files_equals "$expected" "$actual" -} -``` -```[Output] -✓ Passed: Success -✗ Failed: Failure - Expected '/tmp/file1.txt' - Compared '/tmp/file2.txt' - Diff '@@ -1 +1 @@ --file content -+different content' -``` -::: +- assert_files_not_equals is the inverse of this assertion and takes the same arguments. + ## assert_not_same +-------------- > `assert_not_same "expected" "actual"` Reports an error if the two variables `expected` and `actual` are the same value. -[assert_same](#assert-same) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - assert_not_same "foo" "bar" -} +- assert_same is the inverse of this assertion and takes the same arguments. -function test_failure() { - assert_not_same "foo" "foo" -} -``` -::: ## assert_not_contains +-------------- > `assert_not_contains "needle" "haystack"` Reports an error if `needle` is a substring of `haystack`. -[assert_contains](#assert-contains) is the inverse of this assertion and takes the same arguments. +- assert_contains is the inverse of this assertion and takes the same arguments. -::: code-group -```bash [Example] -function test_success() { - assert_not_contains "baz" "foobar" -} - -function test_failure() { - assert_not_contains "foo" "foobar" -} -``` -::: ## assert_string_not_starts_with +-------------- > `assert_string_not_starts_with "needle" "haystack"` Reports an error if `haystack` does starts with `needle`. -[assert_string_starts_with](#assert-string-starts-with) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - assert_string_not_starts_with "bar" "foobar" -} +- assert_string_starts_with is the inverse of this assertion and takes the same arguments. -function test_failure() { - assert_string_not_starts_with "foo" "foobar" -} -``` -::: ## assert_string_not_ends_with +-------------- > `assert_string_not_ends_with "needle" "haystack"` Reports an error if `haystack` does ends with `needle`. -[assert_string_ends_with](#assert-string-ends-with) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - assert_string_not_ends_with "foo" "foobar" -} +- assert_string_ends_with is the inverse of this assertion and takes the same arguments. -function test_failure() { - assert_string_not_ends_with "bar" "foobar" -} -``` -::: ## assert_not_empty +-------------- > `assert_not_empty "actual"` Reports an error if `actual` is empty. -[assert_empty](#assert-empty) is the inverse of this assertion and takes the same arguments. +- assert_empty is the inverse of this assertion and takes the same arguments. -::: code-group -```bash [Example] -function test_success() { - assert_not_empty "foo" -} - -function test_failure() { - assert_not_empty "" -} -``` -::: ## assert_not_matches +-------------- > `assert_not_matches "pattern" "value"` Reports an error if `value` matches the regular expression `pattern`. -[assert_matches](#assert-matches) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - assert_not_matches "foo$" "foobar" -} +- assert_matches is the inverse of this assertion and takes the same arguments. -function test_failure() { - assert_not_matches "bar$" "foobar" -} -``` -::: ## assert_array_not_contains +-------------- > `assert_array_not_contains "needle" "haystack"` Reports an error if `needle` is an element of `haystack`. -[assert_array_contains](#assert-array-contains) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - local haystack=(foo bar baz) +- assert_array_contains is the inverse of this assertion and takes the same arguments. - assert_array_not_contains "foobar" "${haystack[@]}" -} - -function test_failure() { - local haystack=(foo bar baz) - - assert_array_not_contains "baz" "${haystack[@]}" -} -``` -::: ## assert_file_not_exists +-------------- > `assert_file_not_exists "file"` Reports an error if `file` does exists. -[assert_file_exists](#assert-file-exists) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - local file_path="foo.txt" - touch "$file_path" - rm "$file_path" +- assert_file_exists is the inverse of this assertion and takes the same arguments. - assert_file_not_exists "$file_path" -} - -function test_failed() { - local file_path="foo.txt" - touch "$file_path" - - assert_file_not_exists "$file_path" - rm "$file_path" -} -``` -::: ## assert_file_not_contains +-------------- > `assert_file_not_contains "file" "search"` Reports an error if `file` contains the search string. -[assert_file_contains](#assert-file-contains) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - local file="/tmp/file-path.txt" - echo -e "original content" > "$file" +- assert_file_contains is the inverse of this assertion and takes the same arguments. - assert_file_not_contains "$file" "non existing" -} - -function test_failure() { - local file="/tmp/file-path.txt" - echo -e "original content" > "$file" - - assert_file_not_contains "$file" "content" -} -``` -::: ## assert_directory_not_exists +-------------- > `assert_directory_not_exists "directory"` Reports an error if `directory` exists. -[assert_directory_exists](#assert-directory-exists) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - local directory="/nonexistent_directory" +- assert_directory_exists is the inverse of this assertion and takes the same arguments. - assert_directory_not_exists "$directory" -} - -function test_failure() { - local directory="/var" - - assert_directory_not_exists "$directory" -} -``` -::: ## assert_is_directory_not_empty +-------------- > `assert_is_directory_not_empty "directory"` Reports an error if `directory` is empty. -[assert_is_directory_empty](#assert-is-directory-empty) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - local directory="/etc" +- assert_is_directory_empty is the inverse of this assertion and takes the same arguments. - assert_is_directory_not_empty "$directory" -} - -function test_failure() { - local directory="/home/user/empty_directory" - mkdir "$directory" - - assert_is_directory_not_empty "$directory" -} -``` -::: ## assert_is_directory_not_readable +-------------- > `assert_is_directory_not_readable "directory"` Reports an error if `directory` is readable. -[assert_is_directory_readable](#assert-is-directory-readable) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - local directory="/home/user/test" - chmod -r "$directory" +- assert_is_directory_readable is the inverse of this assertion and takes the same arguments. - assert_is_directory_not_readable "$directory" -} - -function test_failure() { - local directory="/var" - - assert_is_directory_not_readable "$directory" -} -``` -::: ## assert_is_directory_not_writable +-------------- > `assert_is_directory_not_writable "directory"` Reports an error if `directory` is writable. -[assert_is_directory_writable](#assert-is-directory-writable) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - local directory="/home/user/test" - chmod -w "$directory" - - assert_is_directory_not_writable "$directory" -} - -function test_failure() { - local directory="/tmp" - - assert_is_directory_not_writable "$directory" -} -``` -::: +- assert_is_directory_writable is the inverse of this assertion and takes the same arguments. ## assert_files_not_equals +-------------- > `assert_files_not_equals "expected" "actual"` Reports an error if `expected` and `actual` are not equals. -[assert_files_equals](#assert-files-equals) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - local expected="/tmp/file1.txt" - local actual="/tmp/file2.txt" - - echo "file content" > "$expected" - echo "different content" > "$actual" - - assert_files_not_equals "$expected" "$actual" -} - -function test_failure() { - - local expected="/tmp/file1.txt" - local actual="/tmp/file2.txt" - - echo "file content" > "$expected" - echo "file content" > "$actual" - - assert_files_not_equals "$expected" "$actual" -} -``` -```[Output] -✓ Passed: Success -✗ Failed: Failure - Expected '/tmp/file1.txt' - Compared '/tmp/file2.txt' - Diff 'Files are equals' -``` -::: - -## fail -> `fail "failure message"` - -Unambiguously reports an error message. Useful for reporting specific message -when testing situations not covered by any `assert_*` functions. - -::: code-group -```bash [Example] -function test_success() { - if [ "$(date +%-H)" -gt 25 ]; then - fail "Something is very wrong with your clock" - fi -} -function test_failure() { - if [ "$(date +%-H)" -lt 25 ]; then - fail "This test will always fail" - fi -} -``` -::: +- assert_files_equals is the inverse of this assertion and takes the same arguments. diff --git a/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_filtered_assert_docs.snapshot b/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_filtered_assert_docs.snapshot index e0a36bd6..63c6ee31 100644 --- a/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_filtered_assert_docs.snapshot +++ b/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_filtered_assert_docs.snapshot @@ -1,118 +1,25 @@ ## assert_equals +-------------- > `assert_equals "expected" "actual"` Reports an error if the two variables `expected` and `actual` are not equal ignoring the special chars like ANSI Escape Sequences (colors) and other special chars like tabs and new lines. -- [assert_same](#assert-same) is similar but including special chars. +- assert_same is similar but including special chars. -::: code-group -```bash [Example] -function test_success() { - assert_equals "foo" "\e[31mfoo" -} - -function test_failure() { - assert_equals "\e[31mfoo" "\e[31mfoo" -} -``` -::: ## assert_files_equals +-------------- > `assert_files_equals "expected" "actual"` Reports an error if `expected` and `actual` are not equals. -[assert_files_not_equals](#assert-files-not-equals) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - local expected="/tmp/file1.txt" - local actual="/tmp/file2.txt" - - echo "file content" > "$expected" - echo "file content" > "$actual" - - assert_files_equals "$expected" "$actual" -} +- assert_files_not_equals is the inverse of this assertion and takes the same arguments. -function test_failure() { - local expected="/tmp/file1.txt" - local actual="/tmp/file2.txt" - - echo "file content" > "$expected" - echo "different content" > "$actual" - - assert_files_equals "$expected" "$actual" -} -``` -```[Output] -✓ Passed: Success -✗ Failed: Failure - Expected '/tmp/file1.txt' - Compared '/tmp/file2.txt' - Diff '@@ -1 +1 @@ --file content -+different content' -``` -::: ## assert_files_not_equals +-------------- > `assert_files_not_equals "expected" "actual"` Reports an error if `expected` and `actual` are not equals. -[assert_files_equals](#assert-files-equals) is the inverse of this assertion and takes the same arguments. - -::: code-group -```bash [Example] -function test_success() { - local expected="/tmp/file1.txt" - local actual="/tmp/file2.txt" - - echo "file content" > "$expected" - echo "different content" > "$actual" - - assert_files_not_equals "$expected" "$actual" -} - -function test_failure() { - - local expected="/tmp/file1.txt" - local actual="/tmp/file2.txt" - - echo "file content" > "$expected" - echo "file content" > "$actual" - - assert_files_not_equals "$expected" "$actual" -} -``` -```[Output] -✓ Passed: Success -✗ Failed: Failure - Expected '/tmp/file1.txt' - Compared '/tmp/file2.txt' - Diff 'Files are equals' -``` -::: - -## fail -> `fail "failure message"` - -Unambiguously reports an error message. Useful for reporting specific message -when testing situations not covered by any `assert_*` functions. - -::: code-group -```bash [Example] -function test_success() { - if [ "$(date +%-H)" -gt 25 ]; then - fail "Something is very wrong with your clock" - fi -} -function test_failure() { - if [ "$(date +%-H)" -lt 25 ]; then - fail "This test will always fail" - fi -} -``` -::: +- assert_files_equals is the inverse of this assertion and takes the same arguments. From 7a0a426a506de5f8e48fbdf9ca53521c97e28c18 Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Sun, 20 Jul 2025 13:42:02 +0200 Subject: [PATCH 05/10] docs: update changelog --- CHANGELOG.md | 1 + docs/command-line.md | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2866a98..c8dbe627 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - Fixed terminal width detection first tput and fall back stty - Refactor clock optimizing the implementation used to get the time - Update and optimize `--help` message +- Add `--doc [search]` option ## [0.21.0](https://github.com/TypedDevs/bashunit/compare/0.20.0...0.21.0) - 2025-06-18 diff --git a/docs/command-line.md b/docs/command-line.md index ee58a341..d4a74868 100644 --- a/docs/command-line.md +++ b/docs/command-line.md @@ -379,11 +379,14 @@ only matching asserts will be shown. ::: code-group ```bash [Example] -./bashunit --doc equals +./bashunit --doc same ``` ```bash [Output] ## assert_equals ... + +## assert_not_same +... ``` ::: From dfccdda5b6397f727aaa1964820d80db55cc7e56 Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Sun, 20 Jul 2025 13:51:00 +0200 Subject: [PATCH 06/10] fix: doc::print_asserts find all functions not just starting with assert* --- src/doc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc.sh b/src/doc.sh index 10c28759..24ee5f01 100644 --- a/src/doc.sh +++ b/src/doc.sh @@ -7,7 +7,7 @@ function doc::print_asserts() { local print=0 local docstring="" while IFS='' read -r line || [[ -n "$line" ]]; do - if [[ $line =~ ^##\ (assert_[A-Za-z0-9_]+) ]]; then + if [[ $line =~ ^##\ ([A-Za-z0-9_]+) ]]; then local fn="${BASH_REMATCH[1]}" if [[ -z "$search" || "$fn" == *"$search"* ]]; then print=1 From b4e372261c46de45653e1970d7f8b268a3436e3e Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Sun, 20 Jul 2025 13:52:53 +0200 Subject: [PATCH 07/10] refactor: use filter var name instead of search --- src/doc.sh | 4 ++-- ....test_bashunit_should_display_all_assert_docs.snapshot | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/doc.sh b/src/doc.sh index 24ee5f01..d3c6c0a7 100644 --- a/src/doc.sh +++ b/src/doc.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash function doc::print_asserts() { - local search="${1:-}" + local filter="${1:-}" local doc_file="$BASHUNIT_ROOT_DIR/docs/assertions.md" local line local print=0 @@ -9,7 +9,7 @@ function doc::print_asserts() { while IFS='' read -r line || [[ -n "$line" ]]; do if [[ $line =~ ^##\ ([A-Za-z0-9_]+) ]]; then local fn="${BASH_REMATCH[1]}" - if [[ -z "$search" || "$fn" == *"$search"* ]]; then + if [[ -z "$filter" || "$fn" == *"$filter"* ]]; then print=1 echo "$line" docstring="" diff --git a/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_all_assert_docs.snapshot b/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_all_assert_docs.snapshot index 09416ee8..47afbf60 100644 --- a/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_all_assert_docs.snapshot +++ b/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_all_assert_docs.snapshot @@ -394,3 +394,11 @@ Reports an error if `directory` is writable. Reports an error if `expected` and `actual` are not equals. - assert_files_equals is the inverse of this assertion and takes the same arguments. + + +## fail +-------------- +> `fail "failure message"` + +Unambiguously reports an error message. Useful for reporting specific message +when testing situations not covered by any `assert_*` functions. From 0c30ff9b3a85aaa9f4d70087660ef340975b8a90 Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Sun, 20 Jul 2025 13:59:19 +0200 Subject: [PATCH 08/10] refactor: simlify test_bashunit_should_display_all_assert_docs snapshot --- ...it_should_display_all_assert_docs.snapshot | 315 +++--------------- 1 file changed, 45 insertions(+), 270 deletions(-) diff --git a/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_all_assert_docs.snapshot b/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_all_assert_docs.snapshot index 47afbf60..e2204851 100644 --- a/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_all_assert_docs.snapshot +++ b/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_all_assert_docs.snapshot @@ -1,404 +1,179 @@ ## assert_true -------------- -> `assert_true bool|function|command` - -Reports an error if the argument result in a truthy value: `true` or `0`. - -- assert_false is similar but different. - +::ignore:: ## assert_false -------------- -> `assert_false bool|function|command` - -Reports an error if the argument result in a falsy value: `false` or `1`. - -- assert_true is similar but different. - +::ignore:: ## assert_same -------------- -> `assert_same "expected" "actual"` - -Reports an error if the `expected` and `actual` are not the same - including special chars. - -- assert_not_same is the inverse of this assertion and takes the same arguments. -- assert_equals is similar but ignoring the special chars. - +::ignore:: ## assert_equals -------------- -> `assert_equals "expected" "actual"` - -Reports an error if the two variables `expected` and `actual` are not equal ignoring the special chars like ANSI Escape Sequences (colors) and other special chars like tabs and new lines. - -- assert_same is similar but including special chars. - +::ignore:: ## assert_contains -------------- -> `assert_contains "needle" "haystack"` - -Reports an error if `needle` is not a substring of `haystack`. - -- assert_not_contains is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_contains_ignore_case -------------- -> `assert_contains_ignore_case "needle" "haystack"` - -Reports an error if `needle` is not a substring of `haystack`. -Differences in casing are ignored when needle is searched for in haystack. - +::ignore:: ## assert_empty -------------- -> `assert_empty "actual"` - -Reports an error if `actual` is not empty. - -- assert_not_empty is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_matches -------------- -> `assert_matches "pattern" "value"` - -Reports an error if `value` does not match the regular expression `pattern`. - -- assert_not_matches is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_string_starts_with -------------- -> `assert_string_starts_with "needle" "haystack"` - -Reports an error if `haystack` does not starts with `needle`. - -- assert_string_not_starts_with is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_string_ends_with -------------- -> `assert_string_ends_with "needle" "haystack"` - -Reports an error if `haystack` does not ends with `needle`. - -- assert_string_not_ends_with is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_line_count -------------- -> `assert_line_count "count" "haystack"` - -Reports an error if `haystack` does not contain `count` lines. - +::ignore:: ## assert_less_than -------------- -> `assert_less_than "expected" "actual"` - -Reports an error if `actual` is not less than `expected`. - -- assert_greater_than is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_less_or_equal_than -------------- -> `assert_less_or_equal_than "expected" "actual"` - -Reports an error if `actual` is not less than or equal to `expected`. - -- assert_greater_than is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_greater_than -------------- -> `assert_greater_than "expected" "actual"` - -Reports an error if `actual` is not greater than `expected`. - -- assert_less_than is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_greater_or_equal_than -------------- -> `assert_greater_or_equal_than "expected" "actual"` - -Reports an error if `actual` is not greater than or equal to `expected`. - -- assert_less_or_equal_than is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_exit_code -------------- -> `assert_exit_code "expected" "callable"` - -Reports an error if the exit code of `callable` is not equal to `expected`. - -If `callable` is not provided, it takes the last executed command or function instead. - -- assert_successful_code, assert_general_error and assert_command_not_found -are more semantic versions of this assertion, for which you don't need to specify an exit code. - +::ignore:: ## assert_array_contains -------------- -> `assert_array_contains "needle" "haystack"` - -Reports an error if `needle` is not an element of `haystack`. - -- assert_array_not_contains is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_successful_code -------------- -> `assert_successful_code "callable"` - -Reports an error if the exit code of `callable` is not successful (`0`). - -If `callable` is not provided, it takes the last executed command or function instead. - -- assert_exit_code is the full version of this assertion where you can specify the expected exit code. - +::ignore:: ## assert_general_error -------------- -> `assert_general_error "callable"` - -Reports an error if the exit code of `callable` is not a general error (`1`). - -If `callable` is not provided, it takes the last executed command or function instead. - -- assert_exit_code is the full version of this assertion where you can specify the expected exit code. - +::ignore:: ## assert_command_not_found -------------- -> `assert_general_error "callable"` - -Reports an error if `callable` exists. -In other words, if executing `callable` does not return a command not found exit code (`127`). - -If `callable` is not provided, it takes the last executed command or function instead. - -- assert_exit_code is the full version of this assertion where you can specify the expected exit code. - +::ignore:: ## assert_file_exists -------------- -> `assert_file_exists "file"` - -Reports an error if `file` does not exists, or it is a directory. - -- assert_file_not_exists is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_file_contains -------------- -> `assert_file_contains "file" "search"` - -Reports an error if `file` does not contains the search string. - -- assert_file_not_contains is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_is_file -------------- -> `assert_is_file "file"` - -Reports an error if `file` is not a file. - +::ignore:: ## assert_is_file_empty -------------- -> `assert_is_file_empty "file"` - -Reports an error if `file` is not empty. - +::ignore:: ## assert_directory_exists -------------- -> `assert_directory_exists "directory"` - -Reports an error if `directory` does not exist. - -- assert_directory_not_exists is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_is_directory -------------- -> `assert_is_directory "directory"` - -Reports an error if `directory` is not a directory. - +::ignore:: ## assert_is_directory_empty -------------- -> `assert_is_directory_empty "directory"` - -Reports an error if `directory` is not an empty directory. - -- assert_is_directory_not_empty is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_is_directory_readable -------------- -> `assert_is_directory_readable "directory"` - -Reports an error if `directory` is not a readable directory. - -- assert_is_directory_not_readable is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_is_directory_writable -------------- -> `assert_is_directory_writable "directory"` - -Reports an error if `directory` is not a writable directory. - -- assert_is_directory_not_writable is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_files_equals -------------- -> `assert_files_equals "expected" "actual"` - -Reports an error if `expected` and `actual` are not equals. - -- assert_files_not_equals is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_not_same -------------- -> `assert_not_same "expected" "actual"` - -Reports an error if the two variables `expected` and `actual` are the same value. - -- assert_same is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_not_contains -------------- -> `assert_not_contains "needle" "haystack"` - -Reports an error if `needle` is a substring of `haystack`. - -- assert_contains is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_string_not_starts_with -------------- -> `assert_string_not_starts_with "needle" "haystack"` - -Reports an error if `haystack` does starts with `needle`. - -- assert_string_starts_with is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_string_not_ends_with -------------- -> `assert_string_not_ends_with "needle" "haystack"` - -Reports an error if `haystack` does ends with `needle`. - -- assert_string_ends_with is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_not_empty -------------- -> `assert_not_empty "actual"` - -Reports an error if `actual` is empty. - -- assert_empty is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_not_matches -------------- -> `assert_not_matches "pattern" "value"` - -Reports an error if `value` matches the regular expression `pattern`. - -- assert_matches is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_array_not_contains -------------- -> `assert_array_not_contains "needle" "haystack"` - -Reports an error if `needle` is an element of `haystack`. - -- assert_array_contains is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_file_not_exists -------------- -> `assert_file_not_exists "file"` - -Reports an error if `file` does exists. - -- assert_file_exists is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_file_not_contains -------------- -> `assert_file_not_contains "file" "search"` - -Reports an error if `file` contains the search string. - -- assert_file_contains is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_directory_not_exists -------------- -> `assert_directory_not_exists "directory"` - -Reports an error if `directory` exists. - -- assert_directory_exists is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_is_directory_not_empty -------------- -> `assert_is_directory_not_empty "directory"` - -Reports an error if `directory` is empty. - -- assert_is_directory_empty is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_is_directory_not_readable -------------- -> `assert_is_directory_not_readable "directory"` - -Reports an error if `directory` is readable. - -- assert_is_directory_readable is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_is_directory_not_writable -------------- -> `assert_is_directory_not_writable "directory"` - -Reports an error if `directory` is writable. - -- assert_is_directory_writable is the inverse of this assertion and takes the same arguments. - +::ignore:: ## assert_files_not_equals -------------- -> `assert_files_not_equals "expected" "actual"` - -Reports an error if `expected` and `actual` are not equals. - -- assert_files_equals is the inverse of this assertion and takes the same arguments. - +::ignore:: ## fail -------------- -> `fail "failure message"` - -Unambiguously reports an error message. Useful for reporting specific message -when testing situations not covered by any `assert_*` functions. +::ignore:: From 8d32a4650aaca05dda749e14a666110e26f5830b Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Sun, 20 Jul 2025 14:05:03 +0200 Subject: [PATCH 09/10] refactor: optimize doc::print_asserts --- src/doc.sh | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/doc.sh b/src/doc.sh index d3c6c0a7..cfee922f 100644 --- a/src/doc.sh +++ b/src/doc.sh @@ -4,29 +4,34 @@ function doc::print_asserts() { local filter="${1:-}" local doc_file="$BASHUNIT_ROOT_DIR/docs/assertions.md" local line - local print=0 local docstring="" + local fn="" + local should_print=0 + while IFS='' read -r line || [[ -n "$line" ]]; do if [[ $line =~ ^##\ ([A-Za-z0-9_]+) ]]; then - local fn="${BASH_REMATCH[1]}" + fn="${BASH_REMATCH[1]}" if [[ -z "$filter" || "$fn" == *"$filter"* ]]; then - print=1 + should_print=1 echo "$line" docstring="" else - print=0 + should_print=0 fi continue fi - if [[ $print -eq 1 ]]; then + if (( should_print )); then if [[ "$line" =~ ^\`\`\` ]]; then - print=0 echo "--------------" echo "$docstring" + should_print=0 continue fi + [[ "$line" == "::: code-group" ]] && continue + + # Remove markdown link brackets and anchor tags line="${line//[\[\]]/}" line="$(sed -E 's/ *\(#[-a-z0-9]+\)//g' <<< "$line")" docstring+="$line"$'\n' From 914b0a7a58ac83a2f472a2e7faf92a9fdd4c7215 Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Sun, 20 Jul 2025 14:08:15 +0200 Subject: [PATCH 10/10] refactor: sort console_header output --- src/console_header.sh | 8 ++++---- ...h.test_bashunit_without_path_env_nor_argument.snapshot | 8 ++++---- ...nit_test_sh.test_bashunit_should_display_help.snapshot | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/console_header.sh b/src/console_header.sh index ea4133f2..a6225de1 100644 --- a/src/console_header.sh +++ b/src/console_header.sh @@ -72,6 +72,10 @@ Options: --debug [file] Enable shell debug mode. Logs to file if provided. + --doc + Display the documentation for assert functions. When a filter is + provided, only matching asserts will be shown. + -e, --env, --boot Load a custom env/bootstrap file to override .env or define globals. @@ -81,10 +85,6 @@ Options: -h, --help Show this help message. - --doc - Display the documentation for assert functions. When a filter is - provided, only matching asserts will be shown. - --init [dir] Generate a sample test suite in current or specified directory. diff --git a/tests/acceptance/snapshots/bashunit_path_test_sh.test_bashunit_without_path_env_nor_argument.snapshot b/tests/acceptance/snapshots/bashunit_path_test_sh.test_bashunit_without_path_env_nor_argument.snapshot index fb87f7e8..ce3b720a 100644 --- a/tests/acceptance/snapshots/bashunit_path_test_sh.test_bashunit_without_path_env_nor_argument.snapshot +++ b/tests/acceptance/snapshots/bashunit_path_test_sh.test_bashunit_without_path_env_nor_argument.snapshot @@ -19,6 +19,10 @@ Options: --debug [file] Enable shell debug mode. Logs to file if provided. + --doc + Display the documentation for assert functions. When a filter is + provided, only matching asserts will be shown. + -e, --env, --boot Load a custom env/bootstrap file to override .env or define globals. @@ -28,10 +32,6 @@ Options: -h, --help Show this help message. - --doc - Display the documentation for assert functions. When a filter is - provided, only matching asserts will be shown. - --init [dir] Generate a sample test suite in current or specified directory. diff --git a/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_help.snapshot b/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_help.snapshot index aee3bb79..c57d3b1e 100644 --- a/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_help.snapshot +++ b/tests/acceptance/snapshots/bashunit_test_sh.test_bashunit_should_display_help.snapshot @@ -18,6 +18,10 @@ Options: --debug [file] Enable shell debug mode. Logs to file if provided. + --doc + Display the documentation for assert functions. When a filter is + provided, only matching asserts will be shown. + -e, --env, --boot Load a custom env/bootstrap file to override .env or define globals. @@ -27,10 +31,6 @@ Options: -h, --help Show this help message. - --doc - Display the documentation for assert functions. When a filter is - provided, only matching asserts will be shown. - --init [dir] Generate a sample test suite in current or specified directory.