parseOutput.rb revision 289997
1174199Srwatson#============================================================ 2174199Srwatson# Author: John Theofanopoulos 3174199Srwatson# A simple parser. Takes the output files generated during the build process and 4174199Srwatson# extracts information relating to the tests. 5174199Srwatson# 6174199Srwatson# Notes: 7174199Srwatson# To capture an output file under VS builds use the following: 8174199Srwatson# devenv [build instructions] > Output.txt & type Output.txt 9174199Srwatson# 10174199Srwatson# To capture an output file under GCC/Linux builds use the following: 11174199Srwatson# make | tee Output.txt 12174199Srwatson# 13174199Srwatson# To use this parser use the following command 14174199Srwatson# ruby parseOutput.rb [options] [file] 15174199Srwatson# options: -xml : produce a JUnit compatible XML file 16174199Srwatson# file : file to scan for results 17174199Srwatson#============================================================ 18174199Srwatson 19174199Srwatson 20174199Srwatsonclass ParseOutput 21174199Srwatson# The following flag is set to true when a test is found or false otherwise. 22174199Srwatson @testFlag 23174199Srwatson @xmlOut 24174199Srwatson @arrayList 25174199Srwatson @totalTests 26174199Srwatson @classIndex 27174199Srwatson 28174199Srwatson# Set the flag to indicate if there will be an XML output file or not 29186567Srwatson def setXmlOutput() 30174199Srwatson @xmlOut = true 31174530Srwatson end 32174199Srwatson 33174199Srwatson# if write our output to XML 34174199Srwatson def writeXmlOuput() 35221807Sstas output = File.open("report.xml", "w") 36174199Srwatson output << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" 37174199Srwatson @arrayList.each do |item| 38174199Srwatson output << item << "\n" 39174199Srwatson end 40174199Srwatson output << "</testsuite>\n" 41174199Srwatson end 42174199Srwatson 43249678Strociny# This function will try and determine when the suite is changed. This is 44174199Srwatson# is the name that gets added to the classname parameter. 45249678Strociny def testSuiteVerify(testSuiteName) 46249678Strociny if @testFlag == false 47174199Srwatson @testFlag = true; 48174199Srwatson # Split the path name 49233390Strociny testName = testSuiteName.split("/") 50174199Srwatson # Remove the extension 51249678Strociny baseName = testName[testName.size - 1].split(".") 52174199Srwatson @testSuite = "test." + baseName[0] 53249678Strociny printf "New Test: %s\n", @testSuite 54174199Srwatson end 55249678Strociny end 56233390Strociny 57233390Strociny 58221807Sstas# Test was flagged as having passed so format the output 59174530Srwatson def testPassed(array) 60233390Strociny lastItem = array.length - 1 61174199Srwatson testName = array[lastItem - 1] 62174199Srwatson testSuiteVerify(array[@className]) 63 printf "%-40s PASS\n", testName 64 if @xmlOut == true 65 @arrayList.push " <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\"/>" 66 end 67 end 68 69# Test was flagged as being ingored so format the output 70 def testIgnored(array) 71 lastItem = array.length - 1 72 testName = array[lastItem - 2] 73 reason = array[lastItem].chomp 74 testSuiteVerify(array[@className]) 75 printf "%-40s IGNORED\n", testName 76 if @xmlOut == true 77 @arrayList.push " <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\">" 78 @arrayList.push " <skipped type=\"TEST IGNORED\"> " + reason + " </skipped>" 79 @arrayList.push " </testcase>" 80 end 81 end 82 83# Test was flagged as having failed so format the line 84 def testFailed(array) 85 lastItem = array.length - 1 86 testName = array[lastItem - 2] 87 reason = array[lastItem].chomp + " at line: " + array[lastItem - 3] 88 testSuiteVerify(array[@className]) 89 printf "%-40s FAILED\n", testName 90 if @xmlOut == true 91 @arrayList.push " <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\">" 92 @arrayList.push " <failure type=\"ASSERT FAILED\"> " + reason + " </failure>" 93 @arrayList.push " </testcase>" 94 end 95 end 96 97 98# Figure out what OS we are running on. For now we are assuming if it's not Windows it must 99# be Unix based. 100 def detectOS() 101 myOS = RUBY_PLATFORM.split("-") 102 if myOS.size == 2 103 if myOS[1] == "mingw32" 104 @className = 1 105 else 106 @className = 0 107 end 108 else 109 @className = 0 110 end 111 112 end 113 114# Main function used to parse the file that was captured. 115 def process(name) 116 @testFlag = false 117 @arrayList = Array.new 118 119 detectOS() 120 121 puts "Parsing file: " + name 122 123 124 testPass = 0 125 testFail = 0 126 testIgnore = 0 127 puts "" 128 puts "=================== RESULTS =====================" 129 puts "" 130 File.open(name).each do |line| 131 # Typical test lines look like this: 132 # <path>/<test_file>.c:36:test_tc1000_opsys:FAIL: Expected 1 Was 0 133 # <path>/<test_file>.c:112:test_tc5004_initCanChannel:IGNORE: Not Yet Implemented 134 # <path>/<test_file>.c:115:test_tc5100_initCanVoidPtrs:PASS 135 # 136 # where path is different on Unix vs Windows devices (Windows leads with a drive letter) 137 lineArray = line.split(":") 138 lineSize = lineArray.size 139 # If we were able to split the line then we can look to see if any of our target words 140 # were found. Case is important. 141 if lineSize >= 4 142 # Determine if this test passed 143 if line.include? ":PASS" 144 testPassed(lineArray) 145 testPass += 1 146 elsif line.include? ":FAIL:" 147 testFailed(lineArray) 148 testFail += 1 149 elsif line.include? ":IGNORE:" 150 testIgnored(lineArray) 151 testIgnore += 1 152 # If none of the keywords are found there are no more tests for this suite so clear 153 # the test flag 154 else 155 @testFlag = false 156 end 157 else 158 @testFlag = false 159 end 160 end 161 puts "" 162 puts "=================== SUMMARY =====================" 163 puts "" 164 puts "Tests Passed : " + testPass.to_s 165 puts "Tests Failed : " + testFail.to_s 166 puts "Tests Ignored : " + testIgnore.to_s 167 @totalTests = testPass + testFail + testIgnore 168 if @xmlOut == true 169 heading = "<testsuite tests=\"" + @totalTests.to_s + "\" failures=\"" + testFail.to_s + "\"" + " skips=\"" + testIgnore.to_s + "\">" 170 @arrayList.insert(0, heading) 171 writeXmlOuput() 172 end 173 174 # return result 175 end 176 177 end 178 179# If the command line has no values in, used a default value of Output.txt 180parseMyFile = ParseOutput.new 181 182if ARGV.size >= 1 183 ARGV.each do |a| 184 if a == "-xml" 185 parseMyFile.setXmlOutput(); 186 else 187 parseMyFile.process(a) 188 break 189 end 190 end 191end 192