Sunday, July 03, 2011

How A Simple Test Script Evolve

I will try to walk you through how a simple test script evolve from a one-time throw-away script to a more generic program that can be re-use.

The requirement is pretty simple. "Can I have a script to submit program-a to run 5 times for 10 minutes, 3 times for 5 minutes and 2 times for half an hour?". There you go with a one-time throw-away script. BTW, this is supposed to run on a Linux system

#! /bin/sh

./program-a --duration 600
./program-a --duration 600
./program-a --duration 600
./program-a --duration 600
./program-a --duration 600

./program-a --duration 300
./program-a --duration 300
./program-a --duration 300

./program-a --duration 1800
./program-a --duration 1800

Our job is done. What if the requirement for duration needs to be changed and we will have to modify quite a few places in the above script. So the script evolved to do some looping.

#! /bin/sh

for i in 1 2 3 4 5
do
    ./program-a --duration 600
done

for i in 1 2 3
do
    ./program-a --duration 300
done

for i in 1 2
do
   ./program-a --duration 1800
done

Not too bad! But there are still a few places where we hard code things like how many times we loop and the duration. OK, may be we can do some form of input instead of fix values

#! /bin/sh

while read duration howmany
do
    seq $howmany | while read count
    do
        ./program-a --duration $duration
    done
done <<EOF
600 5
300 3
1800 2
EOF

Now all I have to do is to change the input data (within the EOF) in the script to control the duration in seconds and how many times to loop through. Hey, but I still need to modify the program every time there is a change in requirement. Can't we have that information to be controlled by input arguments. Also, I want to tell the script in terms of day/hour/minute/second instead of just seconds because I am lazy to calculate. Not a problem at all. Let say the input argument takes the form of "1d23h45m6sx7" to represent looping through the prgroam 7 times with a duration of 1 day 23 hours 45 minutes 6 seconds (that is 171906 seconds, if you work it out). This calculation can be easily done by using sed to substitute day (d) with '*86400+', hour (h) with '*3600+', minute (m) with '*60+' and second (s) with ''. You also need to remove any ending '+' to avoid illegal arthematic epxpression.

#! /bin/sh

if [ $# -eq 0 ]; then
    echo "Usage: $0  [?d?h?m?sx?]"
    echo "       Eg. $0 1d23h45m6sx17 4h30sx8 1hx7"
    exit 1
fi


# check arg syntax
for arg in $@
do
    echo $arg | egrep '^([1-9][0-9]*d)?([1-9][0-9]*h)?([1-9][0-9]*m)?([1-9][0-9]*s)?x[1-9][0-9]*$' > /dev/null 
    if [ $? -ne 0 ]; then
        echo "Error. $arg syntax not correct"
        exit 2
    fi
done


for arg in $@
do

    duration=`echo ${arg%x*} | sed -e 's/d/*86400+/;s/h/*3600+/;s/m/*60+/;s/s//;s/+$//' | bc`
    for count in `seq ${arg#*x}`
    do
        ./program-a --duration $duration
    done
done

If you need to run program-a 1.5 day once, 3 hour and 5 seconds twice and 30 minutes thrice, all you need to do is
./loop.sh 1d12hx1 3h5sx2 30mx3
I hope this blog shows you how a simple script can evolve into something so generic that your future test scripts can be based on.

Labels: