-1

I wrote the below code to extract the testcase name and the PASSED/FAILED status. The testcase log is like below: : In between there are so many lines.

I just want to extract the testcase name ( say A_HL_INT_GPRS_CGDSCONT_0000 and it's PASSED or FAILED status).

Also, another concern is : I have used grep, which is taking a longer time, to execute the shell script.

I need to use AWK or SED commands to solve the below problem.

One more thing I need is : I need to print ALL the failed testcases names like:

failed testcases list:

A_HL_INT_GPRS_CGDCONT_0002 Failed
A_HL_INT_GPRS_CGDCONT_0003 Failed
A_HL_INT_GPRS_CGDCONT_0004 Failed
Begin of A_HL_INT_GPRS_CGDSCONT_0000 
Passed
End of A_HL_INT_GPRS_CGDSCONT_0000 
Begin of A_HL_INT_GPRS_CGDCONT_0002
FAILED
End of A_HL_INT_GPRS_CGDCONT_0002 
#! /bin/bash
echo "Enter the logfilename : "
read logfilename
echo "Entered name : $logfilename"
echo "outside the while loop"
let success=0
let failure=0
let total=0
DONE=false
until $DONE; do
read line || DONE=true
    echo "$line" | grep "Begin of "
    if (echo "$line" | grep -i "PASSED") then
        ((success++))
    fi
    if (echo "$line" | grep -i "FAILED") then
        ((failure++))
    fi
    if (echo "$line" | grep "End of ") then
        ((total++))
    fi  
done < "$logfilename"   
echo "Total testcases : $total"
echo "Total testcase with Success : $success"
echo "Total testcase with Failure : $failure"

Hi Bodo:

I added the below lines alogn with your code:

#! /bin/bash
echo -n "Enter the logfilename : "
read logfilename
echo "Entered name : $logfilename"
echo "outside the while loop"

awk 'BEGIN { IGNORECASE=1; }
/^begin of / { print; count=1; passed=failed=0;}
/^end of / { count=0; totalcount++; if(failed)failcount++;else if(passed)passcount++;}
/passed/ && count { passed=1; }
/failed/ && count { failed=1; }
END {
  print "Total testcases : " totalcount;
  print "Total testcase with Success : " passcount;
  print "Total testcase with Failure : " failcount; }' "logfilename"

Hi Wrutel,

Could you please correct the below code: I was trying to chomp off the line "Begin of TESTCASENAME" and just trying to store the FAILED testcases in an array and later print the list of failed testcases. Also, I was trying to handle, the case - what if logfile is not present:

#! /bin/bash
declare -a arr
# if no command line argument is given
# set logfilename to : logfilename not specified
if [ -z $0 ]
then
  logfilename="*** Log filename not specified.***"
elif [ -n $1 ]
then
# otherwise make first arg as logfilename
  logfilename=$1
fi

echo "outside the while loop"
let success=0
let failure=0
let total=0
let fail=0
while read line; do
        case "$line" in
                *Begin\ of\ *)  echo $line;;
                *PASSED*)       ((success++));;
                *FAILED*)       ((failure++))
                    arr[$fail] = $line
                    echo "Shubhra added this line : ${arr[$fail]}"
                    ((fail++));;
                *End\ of\ *)    ((total++));;
        esac
done < "$logfilename"

echo "Total testcases : $total"
echo "Total testcase with Success : $success"
echo "Total testcase with Failure : $failure"
echo "failed testcase list:"
echo ${arr[@]}
  • Your problem is not grep being slow, but the way your script is written. For example, instead of incrementing your "success" value slowly, you could do it in one go: grep -i "success" | wc -l. I feel like it would be way more performant if the entire script was designed this way, instead of being a giant for-each loop. – Panki May 22 at 14:23
  • @Panki I need the testcase name (A_HL_INT_GPRS_CGDSCONT_0000) and against the name I need to write failed or passed. How to use wc -l and extracting testcase name together in a single command, pls help! – Shubhra Garg May 22 at 16:05
2

The solution here is to use builtin commands in the shell, as then there are not multiple fork/execs per line being done, which are relatively very expensive.

I would do it like this:

#! /bin/bash
echo -n "Enter the logfilename : "
read logfilename
echo "Entered name : $logfilename"
echo "outside the while loop"
let success=0
let failure=0
let total=0
failedtests=()

while read line; do
        case "$line" in
                *Begin\ of\ *)  echo $line
                                failedtests+=( ${line/Begin of /} )
                                ;;
                *PASSED*)       ((success++));;
                *FAILED*)       ((failure++));;
                *End\ of\ *)    ((total++));;
        esac
done < "$logfilename"

echo "Total testcases : $total"
echo "Total testcase with Success : $success"
echo "Total testcase with Failure : $failure"
echo "Failed tests:" ${failedtests[@]}

You can use case to match glob patterns. According to your example data (which has "Passed" and not "PASSED" which you grep for) the leading * of each pattern could be left out, however with it, it matches the grep usage exactly.

I've also done away with the DONE variable, as you loop over the final empty string (resulting from the end-of-file) uselessly.

EDIT: Added collecting and showing the failed tests. These are collected in the bash array failedtests. The ${line/Begin of /} results in the contents of line with that string removed. Finally the complete contents of the array are shown with ${failedtests[@]}.

  • @wrutel : could you please add the code, so that ALL the failed testcase names are listed ? The testcase name we can pick and process from the "Begin of testcasename" line or from "End of testcase name line" – Shubhra Garg May 23 at 12:59
  • @wrutel : Can you write code, to chomp off the "=====Begin of Testcasename=====". I just need the testcase name from that line and display trhe failed testcases list only. – Shubhra Garg May 24 at 6:58
2

You can use the following script if your AWK supports the variable IGNORECASE to force case insensitive comparisons. (GNU AWK, e.g. on Linux supports this.)

If your AWK doesn't support IGNORECASE, you could

  • modify all match patterns to case insensitive patterns, e.g. /[Pp][Aa][Ss][Ss][Ee][Dd]/ instead of /passed/ etc. or
  • use function tolower with the value to be matched, e.g. tolower($0) ~ /passed/ instead of /passed/ etc.
awk 'BEGIN { IGNORECASE=1; }
/^begin of / { print; count=1; passed=failed=0;}
/^end of / { count=0; totalcount++; if(failed)failcount++;else if(passed)passcount++;}
/passed/ && count { passed=1; }
/failed/ && count { failed=1; }
END {
  print "Total testcases : " totalcount;
  print "Total testcase with Success : " passcount;
  print "Total testcase with Failure : " failcount; }' logfile

With this input (in file logfile)

Begin of A_HL_INT_GPRS_CGDSCONT_0000
Passed
foo
End of A_HL_INT_GPRS_CGDSCONT_0000
Begin of A_HL_INT_GPRS_CGDCONT_0002
bar
passed
FAILED
End of A_HL_INT_GPRS_CGDCONT_0002
Begin of foo
failed
End of bar
foo
Passed
FAILED
bar

I get this result

Begin of A_HL_INT_GPRS_CGDSCONT_0000
Begin of A_HL_INT_GPRS_CGDCONT_0002
Begin of foo
Total testcases : 3
Total testcase with Success : 1
Total testcase with Failure : 2

Notes:
The edited version of the script counts passed or failed only once between begin of ... and end of ... lines, failed takes precedence over passed.
The script does not check that the identifiers in begin of ... and end of ... match.

  • Hi, I am getting the below error :$ ./test4.sh Enter the logfilename : testlog.log Entered name : testlog.log outside the while loop awk: cmd. line:1: fatal: cannot open file `logfilename' for reading (No such file or directory) – Shubhra Garg May 23 at 12:26
  • @ShubhraGarg WIthout seeing your script test4.sh it is difficult to find bugs. I guess you have written awk '...' logfilename instead of awk '...' "$logfilename". – Bodo May 23 at 16:00
  • I have added the code at the top, with your name. Pls correct it. – Shubhra Garg May 24 at 6:56
  • Can you add more lines in wrutel's code, for getting the list of failed testcases. I am adding the code ( were array arr is creating the problem ). it seems wrutel is not seeing the page. – Shubhra Garg May 24 at 7:01
  • @ShubhraGarg Why don't you try the suggestion from my comment first? If you need help with basic problems I suggest to read a basic shell script tutorial. – Bodo May 24 at 8:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.