diff --git a/docs/assertions.md b/docs/assertions.md index 6fefe26c..971db190 100644 --- a/docs/assertions.md +++ b/docs/assertions.md @@ -560,6 +560,31 @@ function test_interactive_prompt() { ``` ::: +## assert_arrays_equal +> `assert_arrays_equal "expected..." -- "actual..."` + +Reports an error if the arrays have different lengths or any element differs at the same index. + +Use `--` to separate the expected array from the actual array. + +::: code-group +```bash [Example] +function test_success() { + local expected=(foo bar baz) + local actual=(foo bar baz) + + assert_arrays_equal "${expected[@]}" -- "${actual[@]}" +} + +function test_failure() { + local expected=(foo bar baz) + local actual=(foo baz bar) + + assert_arrays_equal "${expected[@]}" -- "${actual[@]}" +} +``` +::: + ## assert_array_contains > `assert_array_contains "needle" "haystack"` diff --git a/src/assert_arrays.sh b/src/assert_arrays.sh index f18f6278..94672151 100644 --- a/src/assert_arrays.sh +++ b/src/assert_arrays.sh @@ -1,5 +1,57 @@ #!/usr/bin/env bash +function assert_arrays_equal() { + bashunit::assert::should_skip && return 0 + + local label + label="$(bashunit::assert::label)" + + local -a expected_values=() + local -a actual_values=() + local found_separator=false + local argument + + for argument in "$@"; do + if [ "$found_separator" = false ] && [ "$argument" = "--" ]; then + found_separator=true + continue + fi + + if [ "$found_separator" = true ]; then + actual_values[${#actual_values[@]}]="$argument" + else + expected_values[${#expected_values[@]}]="$argument" + fi + done + + if [ "$found_separator" = false ]; then + bashunit::assert::mark_failed + bashunit::console_results::print_failed_test "$label" "--" "but got " "missing array separator" + return + fi + + if [ "${#expected_values[@]}" -ne "${#actual_values[@]}" ]; then + bashunit::assert::mark_failed + bashunit::console_results::print_failed_test \ + "$label" "${expected_values[*]}" "but got " "${actual_values[*]}" \ + "Expected length" "${#expected_values[@]}, actual length ${#actual_values[@]}" + return + fi + + local index + for ((index = 0; index < ${#expected_values[@]}; index++)); do + if [ "${expected_values[$index]}" != "${actual_values[$index]}" ]; then + bashunit::assert::mark_failed + bashunit::console_results::print_failed_test \ + "$label" "${expected_values[*]}" "but got " "${actual_values[*]}" \ + "Different index" "$index" + return + fi + done + + bashunit::state::add_assertions_passed +} + function assert_array_contains() { bashunit::assert::should_skip && return 0 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 3bfd9242..e8232e44 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 @@ -236,6 +236,15 @@ Use `--stdout-contains` / `--stdout-not-contains` (and the `stderr-*` variants) for substring matching when you don't want to assert against the full output. +## assert_arrays_equal +-------------- +> `assert_arrays_equal "expected..." -- "actual..."` + +Reports an error if the arrays have different lengths or any element differs at the same index. + +Use `--` to separate the expected array from the actual array. + + ## assert_array_contains -------------- > `assert_array_contains "needle" "haystack"` diff --git a/tests/unit/assert_advanced_test.sh b/tests/unit/assert_advanced_test.sh index 084c8c6f..208442a0 100644 --- a/tests/unit/assert_advanced_test.sh +++ b/tests/unit/assert_advanced_test.sh @@ -118,6 +118,41 @@ function test_unsuccessful_assert_array_not_contains() { "$(assert_array_not_contains "123" "${distros[@]}")" } +function test_successful_assert_arrays_equal() { + local expected_values + expected_values=(Ubuntu 123 Linux\ Mint) + local actual_values + actual_values=(Ubuntu 123 Linux\ Mint) + + assert_empty "$(assert_arrays_equal "${expected_values[@]}" -- "${actual_values[@]}")" +} + +function test_unsuccessful_assert_arrays_equal_with_different_lengths() { + local expected_values + expected_values=(Ubuntu 123 Linux\ Mint) + local actual_values + actual_values=(Ubuntu 123) + + assert_same \ + "$(bashunit::console_results::print_failed_test \ + "Unsuccessful assert arrays equal with different lengths" \ + "Ubuntu 123 Linux Mint" "but got " "Ubuntu 123" "Expected length" "3, actual length 2")" \ + "$(assert_arrays_equal "${expected_values[@]}" -- "${actual_values[@]}")" +} + +function test_unsuccessful_assert_arrays_equal_with_different_elements() { + local expected_values + expected_values=(Ubuntu 123 Linux\ Mint) + local actual_values + actual_values=(Ubuntu 321 Linux\ Mint) + + assert_same \ + "$(bashunit::console_results::print_failed_test \ + "Unsuccessful assert arrays equal with different elements" \ + "Ubuntu 123 Linux Mint" "but got " "Ubuntu 321 Linux Mint" "Different index" "1")" \ + "$(assert_arrays_equal "${expected_values[@]}" -- "${actual_values[@]}")" +} + function test_successful_assert_line_count_empty_str() { assert_empty "$(assert_line_count 0 "")" }