shellunit-testingbats-core

How to create output in a shell function for unit testing with bats?


After setting up a bats test framework that can test shell scripts in some directory, I am trying to expand the bats tests to test a shell function that is written in another shell file named passive_function.sh.

Test setup

I created a template repository to perform shell testing. It contains a file called test_other_shell.bats in folder /test/ with content:

#!./test/libs/bats/bin/bats

load 'libs/bats-support/load'
load 'libs/bats-assert/load'

@test "running the file in /src/active_function.sh." {
    run ./src/active_function.sh 9 33
    assert_output 42
}

And I created a file called main.sh with content:

#!/bin/sh
some_active_function() {
    sum="$1 + $2" | bc -l
    echo "$sum"
}

some_active_function

Test result

Running the bats test from terminal fails with output:

 ✗ running the file in /src/active_function.sh.
   (from function `assert_output' in file test/libs/bats-assert/src/assert.bash, line 239,
    in test file test/test_active_function.bats, line 8)
     `assert_output 42' failed
   
   -- output differs --
   expected : 42
   actual   : 
   --

Function verification

I manually verified this function returns 42 by running:

source ./src/active_function.sh; some_active_function 9 33

from terminal, which prints:

42
42

Question

How can I write a bats test that tests a shell function which returns the addition of input 2 integer numbers?

E.g. if I call somefunc 3 5 the test pass if the function returns 8, and fail otherwise.


Solution

  • sum="$1 + $2" | bc -l
    

    does not set the sum variable to the sum of the numbers:


    Next, when you execute that code, you define the function and then invoke it with no parameters. You need the last line to be

    some_active_functionm "$@"
    

    Also, if you want to test the function you don't really need to run a script:

    @test "running the file in /src/active_function.sh." {
        source ./src/active_function.sh
        output=$(some_active_function 9 33)
        ((output == 42))
    }
    

    Untested. You could probably get away with

    load ./src/active_function.sh
    
    @test "running the file in /src/active_function.sh." {
        output=$(some_active_function 9 33)
        ((output == 42))
    }