Last Updated: February 25, 2016
·
1.876K
· lukemadhanga

Shell Script to Run PHPUnit Tests With or Without Code Coverage

At my workplace there has been a large impetus for us to fully embrace test-driven development. This, coupled with my desire to get more familiar with shellscript inspired me to modify my unit test script to be, well, more useful.

The previous one simply iterated through a folder and ran all tests in that folder one by one, something PHPUnit does by default. This became a problem when we wanted to render code coverage results because we kept overwriting the results and therefore only the last result was ever visible. Useless. Running PHPUnit whilst rendering code coverage (let's call it CC from now on, my fingers don't like the unnecessary repetition) was significantly slower (even on the beasts we use at work) therefore one of the requirements was that the script should be able to run without generating CC if the user did not want it.

So to run my function to generate code coverage, I do

./rununittests -c html 

Otherwise for a normal run, I would simply run

./rununittests

USAGE

rununittests [-c clover|craph4j|html|php|text] [-d path/to/coverage/output]
-c [coverage type]          Create code coverage
-d [destination]        The path to save the code coverage
-h                          This help
-?                          This help

And the code

## rununittests
# The function to show the help
showHelp () {
        echo ""
        echo "Usage";
        echo "rununittests [-c clover|craph4j|html|php|text] [-d path/to/coverage/output]";
        echo "-c [coverage type]            Create code coverage";
        echo "-d [destination]      The path to save the code coverage"
        echo "-h                            This help"
        echo "-?                            This help"
}

# The default destination of the coverage results
dest='temp/unittestresults'

# If option '-c' is passed, the coverage that we will generate
coverage=''
while getopts "c:d:h?" opt; do
    case $opt in
        c) 
            coverage="--coverage-$OPTARG"
            continue
        ;;
        d)
            dest="$OPTARG"
            continue
        ;;
        h|\?)
            showHelp
            exit
        ;;
    esac
done
if [ $coverage ];
    then
        phpunit $coverage $dest --verbose --bootstrap index.php unittests
        exit
    fi
phpunit --verbose --bootstrap index.php unittests

And a quick breakdown of what I was doing

showHelp () {
        echo ""
        echo "Usage";
        echo "rununittests [-c clover|craph4j|html|php|text] [-d path/to/coverage/output]";
        echo "-c [coverage type]            Create code coverage";
        echo "-d [destination]      The path to save the code coverage"
        echo "-h                            This help"
        echo "-?                            This help"
}

All that was done here was declare a function to show the help file should we want to do so more than once.

# The default destination of the coverage results
dest='temp/unittestresults'

# If option '-c' is passed, the coverage that we will generate
coverage=''

All we do here is declare variables that we will use later. Note the absence of space around the equals sign.

while getopts "c:d:h?" opt; do
    case $opt in
        c) 
            coverage="--coverage-$OPTARG"
            continue
        ;;
        d)
            dest="$OPTARG"
            continue
        ;;
        h|\?)
            showHelp
            exit
        ;;
    esac
done

This part of the function is a simple switch statement, called a case esac statement in shell script (I believe).

while getopts "c:d:h?" opt; do

getopts is the function that allows us to pass options to our shell script. The colon after the letter (e.g. c:) means that we are expecting an argument after the option, which is stored in the variable $OPTARG. This means that our possible options in this function are -c [argument], -d [argument], -h and -?.

if [ $coverage ];
    then
        phpunit $coverage $dest --verbose --bootstrap index.php unittests
        exit
    fi
phpunit --verbose --bootstrap index.php unittests

The last part of the script is a simple if statement, bash style. Note the space around the square brackets