简体   繁体   中英

Using ! in arguments to a bash function

I have a bash function that encapsulates a command to report the results to teamcity (continous integration tests). My problem is that I am unable to negate a the result by prepending a ! .

function run_as_teamcity_test
{
    local name="$1"
    shift
    echo "##teamcity[testStarted name='$name' captureStandardOutput='true']"
    if ! $@; then
        ANY_TEST_FAILURE=true
        FAILED_TESTS="${FAILED_TESTS}    ${name}\n"
        echo "##teamcity[testFailed name='$name']"
        echo -e "\033[31mTests failed: $name\033[0m"
    fi
    echo "##teamcity[testFinished name='$name']"
}

This works:

> run_as_teamcity_test "Should be true" echo "OK"
##teamcity[testStarted name='Should be true' captureStandardOutput='true']
OK
##teamcity[testFinished name='Should be true']

This doesn't work:

> run_as_teamcity_test "Should be false" ! echo "Not OK"
##teamcity[testStarted name='Should be false' captureStandardOutput='true']
!: command not found
##teamcity[testFailed name='Should be false']
Tests failed: Should be false
##teamcity[testFinished name='Should be false']

Bash is looking for a command ! instead of using the builtin. Is there a way to get it to use the builtin instead?

You are running into the issue that bash doesn't have first-class functions. The best thing to do is to define a global function and pass the name as an argument.

test_goodtest () { echo "OK"; }
test_badtest () { ! echo "NOT OK"; }

run_as_teamcity_test ()
{
    local name=$1
    echo "##teamcity[testStarted name='$name' captureStandardOutput='true']"
    if ! "$name"; then
        ANY_TEST_FAILURE=true
        FAILED_TESTS="${FAILED_TESTS}    ${name}\n"
        echo "##teamcity[testFailed name='$name']"
        echo -e "\033[31mTests failed: $name\033[0m"
    fi
    echo "##teamcity[testFinished name='$name']"
}

run_as_teamcity_test test_goodteset
run_as_teamcity_test test_badtest

I'm taking the view that the name of the function can double as the name of the test, but you can add separate arguments for each to run_as_teamcity_test if you like.

I ended up using a helper function instead of ! :

function negate
{
    ! "$@"
}

And using it like this:

> run_as_teamcity_test "Should be false" negate echo "Not OK"
##teamcity[testStarted name='Should be false' captureStandardOutput='true']
Not OK
##teamcity[testFailed name='Should be false']
Tests failed: Should be false
##teamcity[testFinished name='Should be false']

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM