I’ve just created some very basic bash script to automate my task, that is to run behat tests for several test directories. It involves passing argument from command line, doing loops on arrays and concatenating strings. See below for more details.
UPDATE: I’ve just updated the post after discovering that the script can be further enhanced by using bash functions. See updated script at the bottom.
The project
The project is not that large, however, there are some 5 or 6 sites on it with multiple environments like development environments for multiple developers, staging and production. I need to run tests for all sites at specific environment. I’m using behat
as tool for running automated tets (BDD). Below is the test directory structure.
|-- test_dir_root |-- site1 | |-- behat.yml | `-- features |-- site2 | |-- behat.yml | `-- features |-- site3 | |-- behat.yml | `-- features |-- site4 | |-- behat.yml | `-- features |-- site5 | |-- behat.yml | `-- features `-- site6 | |-- behat.yml | `-- features `-- run_tests.sh
Strategy
The strategy is simple, go to test’s root directory, loop through all directories (listed in an array) then run the tests with uniform parameters, ex: if I want to run a staging test, it should run tests against staging environment for all sites listed.
Since behat
‘s default behavior is to run in verbose mode, I have to pass some parameters to have a less cluttered test output.
The Script
I’ve put script at the root directory for the tests and name it run_tests.sh
. Below is the code.
#!/bin/sh if [ "$1" == "" ]; then echo "Usage: ./run_tests.sh <production|staging|development>" echo "Ex: ./run_tests.sh staging" exit 1 fi TEST_ROOT_DIR=$(pwd) SITES=("site1" "site2" "site3" "site4" "site5" "site6") echo "Initiating tests..." for i in "${SITES[@]}" do : # Go to test root dir cd "$TEST_ROOT_DIR" TARGET_DIR="$TEST_ROOT_DIR/$i" COMMAND="behat --profile $1 --format progress" cd "$TARGET_DIR" echo "Running tests for $i at $(pwd)" $COMMAND echo "" done
As you can see, it has some basic control structure like if statement, loops and even string concatenation. The code block:
if [ "$1" == "" ]; then
checks if the first command line argument is empty. If you are using two command line arguments, it will be at $2
, third will be at $3
and so on. The code block:
SITES=("site1" "site2" "site3" "site4" "site5" "site6")
declares an array. The array is then used for looping. The code block:
TARGET_DIR="$TEST_ROOT_DIR/$i"
concatenates the string variable $TEST_ROOT_DIR
and $i
with /
at the middle.
Let’s run it. Assuming they all passes, below will be how it will look like.
lysender@darkstar-lenovo-32:/home/data/www/huge_project/behat$ ./run_tests.sh darkstar Initiating tests... Running tests for site1 at /home/data/www/huge_project/behat/site1 .................... 2 scenarios (2 passed) 20 steps (20 passed) 0m0.211s Running tests for site3 at /home/data/www/huge_project/behat/site3 .............................................................. 18 scenarios (18 passed) 62 steps (62 passed) 0m1.238s Running tests for site3 at /home/data/www/huge_project/behat/site3 .................... 2 scenarios (2 passed) 20 steps (20 passed) 0m0.214s Running tests for site4 at /home/data/www/huge_project/behat/site4 .........F.........F (::) failed steps (::) 01. ... 02. ... 2 scenarios (2 failed) 20 steps (18 passed, 2 failed) 0m0.226s Running tests for site5 at /home/data/www/huge_project/behat/site5 .........F.........F (::) failed steps (::) 01. ... 02. ... 2 scenarios (2 failed) 20 steps (18 passed, 2 failed) 0m0.218s Running tests for site6 at /home/data/www/huge_project/behat/site6 .................... 2 scenarios (2 passed) 20 steps (20 passed) 0m0.214s lysender@darkstar-lenovo-32:/home/data/www/huge_project/behat$
That’s it. Enjoy and share.
Update!
After being annoyed by running all tests for all sites every single time, I decided to add an option to I could just run a test for just one site. Therefore, it will either run tests for all sites or run test for just one site. Below is the updated script.
#!/bin/sh if [ "$1" == "" ]; then echo "Usage: ./run_tests.sh <production|staging|development> <optional site_name>" echo "Ex: ./run_tests.sh staging" echo "Ex: ./run_tests.sh staging site2" exit 1 fi TARGET_SITE="" if [ "$2" == "" ]; then SITES=("site1" "site2" "site3" "site4" "site5" "site6") else SITES=("$2") fi BEHAT_PROFILE="$1" TEST_ROOT_DIR=$(pwd) run_behat_test_on_target() { # $1 is root dir # $2 is the target site # $3 is the profile name TARGET_DIR="$1/$2" COMMAND="behat --profile $3 --format progress" cd "$TARGET_DIR" echo "Running tests for $2 at $(pwd)" $COMMAND echo "" } echo "Initiating tests..." for i in "${SITES[@]}" do : run_behat_test_on_target $TEST_ROOT_DIR $i $BEHAT_PROFILE done
To run the script, we doe something like below:
# Run tests for just site 2 ./run_tests.sh staging site2 # Run tests for all sites ./run_tets.sh staging