BATS - How to force a check for existence of a program to fail?

378 Views Asked by At

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.

1

There are 1 best solutions below

2
On BEST ANSWER

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...