I have a function that checks for both the existence of a file and if it's executable.
is_command() {
[[ -x "$(command -v "$1" 2> /dev/null)" ]] && return 0
return 1
}
I have a script that is requiring dos2unix
.
is_command 'dos2unix' || { echo 'dos2unix is required'; exit 1}
Since dos2unix
is installed in /usr/bin
I can't just remove the installed path from PATH
. I also don't want to (and can't anyway) temporarily rename the actual dos2unix program.
I tried setting an entry in BASH_CMDS, and it works from the command line:
$ hash -r ; BASH_CMDS['dos2unix']='/no/such/dir/dos2unix' ; [[ -x "$(command -v dos2unix 2> /dev/null)" ]] ; echo $?
1
But this test is not working. The assert_output does not match (it's usage message from later in the program).
@test 'dos2unix does not exist' {
hash -r
BASH_CMDS['dos2unix']='/no/such/dir/dos2unix'
note "dos2unix: $(command -v dos2unix)"
run ds
assert_failure
assert_output 'dos2unix is required'
}
How can I make this work? and why isn't this working?
Edit: Make the assert_output match the error generated.
Lets say your file-under-test looks like this:
#!/usr/bin/env bash
ds() {
is_command() {
[[ -x "$("${command}" -v "$1" 2> /dev/null)" ]] && return 0
return 1
}
is_command 'dos2unix' || { echo 'dos2unix is required'; exit 1; }
exit 0;
}
You would have to somehow "load" this code into your test before it can be run.
Most often, the BATS's load
function is used for this. However, this (or a similar setup) messes with the scope of BASH_CMDS
.
This can be resolved by sourcing the file from the global scope:
#!/usr/bin/env bats
source "${BATS_TEST_DIRNAME}/ds.sh" # <-- This part is important
@test 'dos2unix does not exist' {
hash -r
BASH_CMDS['dos2unix']='/no/such/dir/dos2unix'
run ds
assert_failure
assert_output 'dos2unix is required'
}
When I run your original code, it indeed fails. With source
, the test passes for me.
If this does not resolve your issue, other things might (also) be going on...