go-script-bash icon indicating copy to clipboard operation
go-script-bash copied to clipboard

File assertions overwrite the value of the `output` and `lines` variables

Open nkakouros opened this issue 6 years ago • 0 comments

Due diligence

  • [x] I am familiar with the "Reporting issues" section of CONTRIBUTING.md
  • [x] I have searched the existing issues and haven't found one that matches what I'm reporting or requesting now.
  • [x] If this is a bug report, I have searched the Bash changelog for information that may explain or provide clues to the behavior I'm observing and reference it in the body of the report.

Framework, Bash, and operating system version information

_GO_CORE_VERSION:         v1.7.0
BASH_VERSION:             4.4.19(1)-release
OSTYPE:                   linux-gnu
_GO_PLATFORM_ID:          arch
_GO_PLATFORM_VERSION_ID:

Description

The function __assert_file that is used by file assertion functions sets the output and lines variables to the content of the file under test in order to take advantage of the other "regular" assert_ functions that operate on these variables. In a test, however, this does not allow the use of a "regular" assertion after a file assertion. For instance, the following will fail:

@test 'demo' {
  run 'ls /'
  assert_file_matches '/etc/passwd' 'root'
  assert_output_matches 'etc'
}

I tried to add around the main body of __assert_file an additional step of storing the output and lines variables if they are already set and then putting back their original values just before __assert_file exits (commented out lines below):

__assert_file() {
  local assertion="$1"
  local file_path="$2"
  shift 2
  local constraints=("$@")

  # if [[ "${output-GO_SCRIPT_UNDEFINED}" != 'GO_SCRIPT_UNDEFINED' ]]; then
  #   old_output="$output"
  #   old_lines=("${lines[@]}")
  # fi

  if ! set_bats_output_and_lines_from_file "$file_path"; then
    return '1'
  fi

  if [[ "$assertion" == 'assert_matches' ]]; then
    if [[ "$#" -ne '1' ]]; then
      printf 'ERROR: %s takes exactly two arguments\n' "${FUNCNAME[1]}" >&2
      return '1'
    fi
    constraints=("$1" "$output" "The content of '$file_path'")
  fi

  "$assertion" "${constraints[@]}"

  # if [[ "${old_output-GO_SCRIPT_UNDEFINED}" != 'GO_SCRIPT_UNDEFINED' ]]; then
    # output="$old_output"
    # lines=("${old_lines[@]}")
  # fi
}

This works but some tests in tests/assertions.bats fail because they rely on the current behavior.

There are two workarounds this without the above change. First option, a test that uses the assert_file_* functions can store output somewhere safe before calling the assert_file_* function.

The second option would be to simply reorder the checks in the test function, so that file assertions go always last. In the above sample test, assert_output_matches should go before assert_file_matches. But this might be a bit counter-intuitive, depending on the application.

Both options require that the behavior is documented so that the developer knows what to do. But to me the best solution seems to be to fix __assert_lines.

nkakouros avatar May 16 '18 22:05 nkakouros