Skip to content

Instantly share code, notes, and snippets.

@jclarkin
Created August 31, 2015 16:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jclarkin/f4ce895a3b7ac4caf476 to your computer and use it in GitHub Desktop.
Save jclarkin/f4ce895a3b7ac4caf476 to your computer and use it in GitHub Desktop.
Perl Script to Generate the Test History based on a collection of JUnit XML file inputs
#!/usr/local/bin/perl
#
# Build Historical Pass/Fail results on all unit tests
#
# Configurables
my $iType = "Geronimo"; # WLS or JBoss or Geronimo
my $iDirInput;
my $iDirOutput;
my $iMax = 100.00;
my $iMin = 0.00;
my $iRunType; # stats or tests
# Input/Output variables
my $iOutput;
################### BODY #################
## Loads all Runtime Parameters passed into the Script
&loadCommands();
my $iFileName = &getFileName($iType);
if($iRunType =~ /stats/) {
print "Generating Statistics...\n";
my %lStats =
%{&generateStatistics( $iDirInput, $iFileName )};
&printStatistics(\%lStats, "$iDirOutput/$iOutput" );
die "Complete!\n";
}
elsif($iRunType =~ /tests/) {
print "Generating Test Case Results...\n";
# die "Complete!\n"
} else {
die "Invalid Run Type\n";
}
# Get a list of all folders to traverse
my @folders = @{&getFolders($iDirInput)};
my %iResults;
my %iBuilds;
# Open the statistic file for each subfolder and analyze
foreach $folder (sort @folders) {
next if (-l "$iDirInput/$folder"); # skip non-directories
next if (-f "$iDirInput/$folder"); # skip non-directories
next if ($folder =~ m/ignore/); # skip selected directories
print "Folder: $folder\n";
my $lFile = "$iDirInput/$folder/$iFileName";
if( !open(STATS, $lFile) ) {
print "Err: Unable to open $lFile\n";
next;
}
my @lines = <STATS>;
close(STATS);
# File Details
my $lBuild = "";
my $lDate = "";
my $lineNo = 0;
my $line = @lines[$lineNo++];
## While line is not </properties> Look for Build Info
while($line !~ m/<\/properties>/) {
if($line =~ m/property name=\"build\.timestamp\"/) {
# Get the TimeStamp
$line =~ m/value=\"([^\ ]+)/;
$lDate = $1;
} elsif($line =~ m/property name=\"build\.label\"/) {
# Get the Build Name
$line =~ m/value=\"([^\"]+)\"/;
$lBuild = $1;
}
# Increment the Line count
$line = @lines[$lineNo++];
}
# Determine the Build no
$folder =~ m/-(\d+)/;
my $lBuildNo = sprintf("%03d", $1);
# Store the build names
$iBuilds{$lBuildNo} = $lBuild;
## For all the remaining lines
my $maxLines = @lines;
for(;$lineNo < $maxLines;) {
my $testName;
my $testState = '?';
## If line has <testcase
if($line =~ m/<testcase/) {
## Get the Test Case Name
$testName = &getTestClassName($line);
## If the line ends in '/>', mark as Pass
if($line =~ m/\"\/>/) {
$testState='';
} elsif($line =~ m/\">/){
## If there is a body to this tag, then there are errors
while($line !~ m/<\/testcase>/) {
## If see '<error' flag as an error
if($line =~ m/<error/) {
$testState='Err';
}
## If see '<failure' flag as a failure
elsif($line =~ m/<failure/) {
$testState='Fail';
}
$line = @lines[$lineNo++];
}
if($testState eq '?') {print "$testState Could Not Find for $lBuildNo: $testName\n";}
} else {
print "Could Not Find for $lBuildNo: $testName\n";
}
## Store that result (if not blank)
if($testState ne '') {
$iResults{$testName}{$lBuild} = $testState;
}
}
# Increment the line count
$line = @lines[$lineNo++];
}
}
### Generate the Statistics
&printHistory(\%iResults, \%iBuilds, "$iDirOutput/$iOutput" );
print "Complete!\n";
################################################################################
################################################################################
################################################################################
################################################################################
################################################################################
sub loadCommands {
my $lVarSize = @ARGV;
my $lErrorMessage =
"Missing Runtime Commands: \n".
" -r Type of run: tests or stats \n".
" -t Which server to run against: JBoss or WLS \n".
" -i Input folder. E.g. C:/0706 \n".
" -o Output folder. E.g. C:/0706/out \n".
" -f Output filename \n".
" \n";
if($lVarSize < 1 or $lVarSize%2 > 0) {
die $lErrorMessage;
}
for (my $lIndex = 0; $lIndex < $lVarSize; $lIndex++) {
my $lCommand = @ARGV[$lIndex++];
my $lText = @ARGV[$lIndex];
if($lCommand eq "-t") {
$iType = $lText; print "For ".$lText."\n";
}
elsif($lCommand eq "-r") {
$iRunType = $lText; print "Run ".$lText."\n";
}
elsif($lCommand eq "-i") {
$iDirInput = $lText; print "Input: '".$lText."'\n";
}
elsif($lCommand eq "-o") {
$iDirOutput = $lText; print "Output: '".$lText."'\n";
}
elsif($lCommand eq "-f") {
$iOutput = $lText; print "Filename: '".$lText."'\n";
}
elsif($lCommand eq "-x") {
$iMax = $lText; print "Max Range: '".$lText."'\n";
}
elsif($lCommand eq "-n") {
$iMin = $lText; print "Min Range: '".$lText."'\n";
}
}
#Validate the input
if(not defined $iType){
die $lErrorMessage;
}
if(not defined $iRunType){
die $lErrorMessage;
}
if(not defined $iDirInput){
die $lErrorMessage;
}
if(not defined $iDirOutput){
die $lErrorMessage;
}
if(not defined $iOutput){
die $lErrorMessage;
}
print "\n";
}
sub getTestClassName {
my $aLine = @_[0];
my $lTestClass;
my $lTestName;
## Get the Name and Class
$aLine =~ m/ name=\"([^\"]+)\"/;
$lTestName = $1;
$aLine =~ m/classname=\"([^\"]+)\"/;
$lTestClass = $1;
# Parse out any WIP naming
if($lTestName =~ m/^(.*)_WIP_/) {
$lTestName = $1;
}
return "$lTestClass,$lTestName";
}
sub getFileName {
my $aType = @_[0];
if($aType eq "JBoss") {
return "results.jboss.xml";
} elsif($aType eq "WLS") {
return "results.weblogic.xml";
} elsif($aType eq "Geronimo") {
return "results.geronimo.xml";
}
return "";
}
sub getFolders {
my $aDir = @_[0];
my @lFolders;
# Open the directory and get a list of all the subfolders
opendir(DIR,"$iDirInput") or die " unable to open the main directory";
@lFolders = grep (!/^\.\.?/, readdir(DIR));
closedir(DIR);
return \@lFolders;
}
################################################################################
#
# Obtains and Prints out the Statistics for the builds
#
# @param aDirInput The directory where all the Build Results folders are located
# @param aFileName The input file to be read from each directory
#
################################################################################
sub generateStatistics {
# IO Variables
my $aDirInput = @_[0];
my $aFileName = @_[1];
my %lStats;
# Open the directory and get a list of all the subfolders
my @folders = @{&getFolders($aDirInput)};
# Open the statistic file for each subfolder and analyze
foreach $folder (sort @folders) {
next if (-l "$aDirInput/$folder"); # skip non-directories
next if (-f "$aDirInput/$folder"); # skip non-directories
next if ($folder =~ m/ignore/); # skip selected directories
print "Folder: $folder\n";
my $lFile = "$aDirInput/$folder/$aFileName";
my @lResults = @{&getStatistics($lFile)};
# Determine the Build no
$folder =~ m/-(\d+)/;
my $lBuildNo = sprintf("%03d", $1);
# Store the results, if any were found
if(@lResults > 0) {
$lStats{$lBuildNo} = \@lResults;
} else {
print "No stats found for $folder.\n";
}
}
# Print the Statistics
return \%lStats;
}
################################################################################
#
# Prints out the History of Pass / Fail / Error Unit Test Cases
#
# @param aResults The Hashmap of all the test results
# @param aBuilds The Hashmap of all the Build names
# @param aOutput The full directory and filename to which the results will be saved
#
################################################################################
sub printHistory {
my %aResults = %{@_[0]};
my %aBuilds = %{@_[1]};
my $aOutput = @_[2];
my $lOutputLine;
# Open/Create the File to publish the results
open(OUT,">$aOutput") or die "Unable to create '$aOutput'\n";
# Setup the initial line: Reverse order of all build names
$lOutputLine = "Package,Name";
foreach $lBuildId (reverse sort keys %aBuilds){
$lBuildName = $aBuilds{$lBuildId};
$lOutputLine = "$lOutputLine,$lBuildName";
}
print OUT "$lOutputLine\n";
# Print out the individual test results: reverse order of builds
foreach my $lTestname (sort keys %aResults) {
$lOutputLine = $lTestname;
foreach $lBuildId (reverse sort keys %aBuilds){
my $lBuildName = $aBuilds{$lBuildId};
my $lTestResult = $aResults{$lTestname}{$lBuildName};
$lOutputLine = "$lOutputLine,$lTestResult";
}
print OUT "$lOutputLine\n";
}
# Close the output file
close(OUT);
return;
}
################################################################################
#
# Prints out the Success Rate of the Unit Tests
#
# @param aBuilds The Hashmap of all the Builds: name, date, tests, failures, errors, %
# @param aOutput The full directory and filename to which the results will be saved
#
################################################################################
sub printStatistics {
my %aBuilds = %{@_[0]};
my $aOutput = @_[1];
my $lOutputLine;
# Open/Create the File to publish the results
open(OUT,">$aOutput") or die "Unable to create '$aOutput'\n";
# Setup the initial line in the Stats file
$lOutputLine = "|| *Date* || *Build* || *Total Tests* || *Total Failures* || *Total Errors* || *Success Rate* || *Notes* ||";
print OUT "$lOutputLine\n";
# Print out the individual test results
foreach $lBuildId (sort keys %aBuilds){
@lBuildDetails = @{$aBuilds{$lBuildId}};
my $lName = @lBuildDetails[0];
my $lDate = @lBuildDetails[1];
my $lTests = @lBuildDetails[2];
my $lFailures = @lBuildDetails[3];
my $lErrors = @lBuildDetails[4];
my $lPercent = @lBuildDetails[5];
$lOutputLine = "| $lDate | $lName | $lTests | $lFailures | $lErrors | $lPercent | |";
print OUT "$lOutputLine\n";
}
# Close the output file
close(OUT);
return;
}
################################################################################
#
# Determines the Success Rate of the Unit Tests for a specific Build
#
# @param aInput The full directory and filename to the file under analysis
#
# @return lResults An array of the build details: name, date, tests, failures, errors, %
#
################################################################################
sub getStatistics {
my $aInput = @_[0];
my @lResults;
# Read in the Build Results File
if( !open(STATS, $aInput) ) {
return @lResults;
}
my @lLines = <STATS>;
close(STATS);
# Test Statistics
my $lName = "";
my $lDate = "";
my $lTotalTests = 0;
my $lTotalErrors = 0;
my $lTotalFailures = 0;
my $lPercentage = 0;
foreach $lLine (@lLines) {
# Three valid cases: timestamp, build name, results
if($lLine =~ m/property name=\"build\.timestamp\"/) {
# Get the TimeStamp
$lLine =~ m/value=\"([^\ ]+)/;
$lDate = $1;
} elsif($lLine =~ m/property name=\"build\.label\"/) {
# Get the Build Name
$lLine =~ m/value=\"([^\"]+)\"/;
$lName = $1;
} elsif ($lLine =~ m/<testsuite/) {
# Get the Statistics
if($lLine =~ m/tests=\"(\d+)\"/) {
$lTotalTests += $1;
}
if($lLine =~ m/failures=\"(\d+)\"/) {
$lTotalFailures += $1;
}
if($lLine =~ m/errors=\"(\d+)\"/) {
$lTotalErrors += $1;
}
}
}
# Calculate Success Rate %
if($lTotalTests > 0) {
my $lTotalBad = ($lTotalErrors+$lTotalFailures);
$lPercentage = ($lTotalTests - $lTotalBad) * 100 / $lTotalTests;
}
$lPercentage = sprintf("%.2f", $lPercentage);
if($lDate == "") {print "ERR: $lFile\n";}
# Store the results: name, date, tests, failures, errors, %
@lResults = ($lName, $lDate, $lTotalTests, $lTotalFailures, $lTotalErrors, $lPercentage);
return \@lResults;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment