sstephenson / bats

Bash Automated Testing System
MIT License
7.13k stars 517 forks source link

Output not captured (or returned) when using function exported from parent process #225

Closed pawamoy closed 6 years ago

pawamoy commented 7 years ago

I was completely lost for a bit but I'm a persevering bug hunter so here is the simplified issue: if at some point in your test, you're using a function that has been exported from a parent process (in your interactive shell for example), and your test(s) fail, the output is not restored (not displayed). Screenshot below.

Here is some code to reproduce:

# tests/test_using_exported_function_in_sourced_file.bats

if exported_function; then
  # declare some variable or whatever
  a_variable="random contents"
fi

@test "should print captured output when failure" {
  echo "PRINT THIS"
  false  # always fail for demonstration purpose
}

bats tests/test_using_exported_function_in_sourced_file.bats

Running bats on this file works, even though exported_function is not defined: we end up with nice warnings before bats output. Now lets create our function in the shell and export it:

exported_function() { true; }
export -f exported_function

bats tests/test_using_exported_function_in_sourced_file.bats

Running bats again will fail (okay), but no output is printed!

screenshot - 07202017 - 06 13 06 pm

The same bug will occur no matter where the exported function is called (from a file loaded with bats' load or bash's . or source).

To prove it is really the exported function causing problem, let's define it in the test file:

# tests/test_using_exported_function_in_sourced_file.bats

exported_function() { true; }
# export -f exported_function  # same effect with or without

if exported_function; then
  # declare some variable or whatever
  a_variable="random contents"
fi

@test "should print captured output when failure" {
  echo "PRINT THIS"
  false  # always fail for demonstration purpose
}

Run bats: bats tests/test_using_exported_function_in_sourced_file.bats Working again!

Is it a bug or am I missing something? Is it related really to bats?

xmik commented 7 years ago

Does this help? https://github.com/sstephenson/bats/issues/191#issuecomment-256947900

pawamoy commented 7 years ago

Nope, I understand that bats is capturing output inside tests, the problem here is that it does not print it when the test fails!

mfdj commented 7 years ago

I tried re-producing your issue but wasn't able to.

I tweaked the script to be a little more concise:

if type -p exported_function; then
  a_variable="random contents"
fi

@test "should print captured output when failure" {
  echo "a_variable '$a_variable'"
  false  # always fail for demonstration purpose
}

I was able to get output in both cases?

screen shot 2017-07-20 at 10 16 04 am

pawamoy commented 7 years ago

Well you do not execute the function here. Try to remove type -p:

#!/usr/bin/env bats

if exported_function; then
  a_variable="random contents"
fi

@test "should print captured output when failure" {
  echo "a_variable '$a_variable'"
  false  # always fail for demonstration purpose
}

Just had the same problem on another machine: capture du 2017-07-21 00-15-55

pawamoy commented 7 years ago

I installed bats with bpkg by the way, version 0.4.0 (sudo bpkg install -g sstephenson/bats)

mfdj commented 7 years ago

Good point — well I tried your variation to be double certain that the execution is the problem but was still not able to reproduce.

screen shot 2017-07-20 at 3 21 52 pm

I tested with Homebrew installed BATS and from source. I also test with bash 3 + 4 as my login shell (I primarily use bash 4):

pawamoy commented 7 years ago

Hmmm... it must come from my shell environment then...

Thank you for the follow up :+1: ! I'm gonna continue the investigation and post updates here :)

pawamoy commented 7 years ago

Seems it happens with some (or all?) versions of Bash 4.3. I just upgraded to Bash 4.4.0 and everything works as expected (output is correctly printed). I won't investigate further to see what change from Bash 4.3 to 4.4 is responsible for the fix so I will close this issue if there are no updates the next few days! Thanks again @mfdj and @xmik

From http://sourcedigit.com/20892-bash-4-4-released-install-bash-shell-ubuntu/

sudo apt-get install build-essential
wget http://ftp.gnu.org/gnu/bash/bash-4.4.tar.gz
tar xf bash-4.4.tar.gz
cd bash-4.4
./configure
make
sudo make install
pawamoy commented 7 years ago

I wrote a test for this particular problem, should I send a PR?

In test/bats.bats:

@test "executing exported function does not break failing test output" {
  exported_function() { :; }
  export -f exported_function
  run bats "$FIXTURE_ROOT/exported_function.bats"
  [ $status -eq 1 ]
  [ "${lines[0]}" = "1..1" ]
  [ "${lines[1]}" = "not ok 1 failing test" ]
  [ "${lines[2]}" = "# (in test file test/fixtures/bats/exported_function.bats, line 9)" ]
  [ "${lines[3]}" = "#   \`false' failed" ]
  [ "${lines[4]}" = "# a='a is set'" ]
}

New file test/fixtures/bats/exported_function.bats:

# see issue #225

if exported_function; then
  a='a is set'
fi

@test "failing test" {
  echo "a='$a'"
  false
}

As expected, it's passing with Bash 4.4 and failing with Bash 4.3 (4.3.11(1)-release).

pawamoy commented 7 years ago

I ran tests with different Bash versions thanks to @aclemons' fork. Conclusion is exported_function test fails everywhere except in Bash 4.4. 🤣

Without patches: https://pastebin.com/kMUqQ3HD With latest patches: https://pastebin.com/8J3uNkMC

pawamoy commented 6 years ago

This was resolved in bats-core/bats-core#87