How to reuse bats unit tests

521 Views Asked by At

I'm looking forward to reuse code for bats unit tests on different environments. What I want to know if it's possible to have common @test code for both files in one place.

My first unit test file is to be run on my development environment:

#!/usr/bin/env bats

load 'test_helper/bats-support/load'
load 'test_helper/bats-assert/load'

setup() {

    # Development environment
    PROJECT_PATH="/d/develop/myproject" 
}

@test 'check project path' {
    cd $PROJECT_PATH
    run git fetch origin
    refute_output --partial 'fatal: not a git repository (or any of the parent directories): .git'
}

My second unit test file runs same test and is to be run on deployment or production environment:

#!/usr/bin/env bats

load 'test_helper/bats-support/load'
load 'test_helper/bats-assert/load'

setup() {

    # Production environment  
    PROJECT_PATH="/var/myproject" 
}

@test 'check project path' {
    cd $PROJECT_PATH
    run git fetch origin
    refute_output --partial 'fatal: not a git repository (or any of the parent directories): .git'
}

As you see code for test is the same and only change $PROJECT_PATH value on the setup function.

Thanks for taking your time to read this question.

1

There are 1 best solutions below

0
On

There are several ways you could solve this:

  1. Simply remove the setup function and set PROJECT_PATH outside the tests.
  2. Set a sensible default (and overwrite that in development).
  3. Make the PROJECT_PATH variable required (and make the test fail if it is not set).
  4. If more tests require environment specific settings, set ENVIRONMENT outside the test(s) and set PROJECT_PATH depending on the value of ENVIRONMENT.

(Please note that only the setup function needs to be changed for this, the check project path @test function stays as-is)

As talk is cheap and code speaks louder than words, here are some examples to demonstrate what I mean with each of these options:

Option 1. Set PROJECT_PATH outside the tests

Remove setup entirely and set PROJECT_PATH before calling BATS:

export PROJECT_PATH="/var/myproject"
bats ./my_test.bats

Option 2. Set a sensible default

Set the production value as a default and allow it to be set from outside the test:

setup() {
    PROJECT_PATH="${PROJECT_PATH:-/var/myproject}"
}

Option 3. Make PROJECT_PATH required

To abort and fail the test if PROJECT_PATH has not been set, replace your current setup with:

setup() {
    if [[ ! -v "${PROJECT_PATH}" ]]; then
        skip 'Required environment variable "$PROJECT_PATH" not set!'
        return 1
    fi
}

Option 4. Use ENVIRONMENT

Instead of depending on PROJECT_PATH directly, set an $ENVIRONMENT when calling BATS and set PROJECT_PATH based on that:

setup() {

    if [[ "${ENVIRONMENT}" == 'development' ]];then
        PROJECT_PATH="/d/develop/myproject"
    elif [[ "${ENVIRONMENT}" == 'production' ]];then
        PROJECT_PATH="/var/myproject"
    else
        skip "Unknow \$ENVIRONMENT: '${ENVIRONMENT}'"
        return 1
    fi
}

Conclusion

Which solution is the best depends on what your desired setup is. Of course, cross-overs between these solutions is also possible. I'll leave that as an exercise tot the reader...