1290001Sglebius#============================================================ 2290001Sglebius# Author: John Theofanopoulos 3290001Sglebius# A simple parser. Takes the output files generated during the build process and 4290001Sglebius# extracts information relating to the tests. 5290001Sglebius# 6290001Sglebius# Notes: 7290001Sglebius# To capture an output file under VS builds use the following: 8290001Sglebius# devenv [build instructions] > Output.txt & type Output.txt 9290001Sglebius# 10290001Sglebius# To capture an output file under GCC/Linux builds use the following: 11290001Sglebius# make | tee Output.txt 12290001Sglebius# 13290001Sglebius# To use this parser use the following command 14290001Sglebius# ruby parseOutput.rb [options] [file] 15290001Sglebius# options: -xml : produce a JUnit compatible XML file 16290001Sglebius# file : file to scan for results 17290001Sglebius#============================================================ 18290001Sglebius 19290001Sglebius 20290001Sglebiusclass ParseOutput 21290001Sglebius# The following flag is set to true when a test is found or false otherwise. 22290001Sglebius @testFlag 23290001Sglebius @xmlOut 24290001Sglebius @arrayList 25290001Sglebius @totalTests 26290001Sglebius @classIndex 27290001Sglebius 28290001Sglebius# Set the flag to indicate if there will be an XML output file or not 29290001Sglebius def setXmlOutput() 30290001Sglebius @xmlOut = true 31290001Sglebius end 32290001Sglebius 33290001Sglebius# if write our output to XML 34290001Sglebius def writeXmlOuput() 35290001Sglebius output = File.open("report.xml", "w") 36290001Sglebius output << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" 37290001Sglebius @arrayList.each do |item| 38290001Sglebius output << item << "\n" 39290001Sglebius end 40290001Sglebius output << "</testsuite>\n" 41290001Sglebius end 42290001Sglebius 43290001Sglebius# This function will try and determine when the suite is changed. This is 44290001Sglebius# is the name that gets added to the classname parameter. 45290001Sglebius def testSuiteVerify(testSuiteName) 46290001Sglebius if @testFlag == false 47290001Sglebius @testFlag = true; 48290001Sglebius # Split the path name 49290001Sglebius testName = testSuiteName.split("/") 50290001Sglebius # Remove the extension 51290001Sglebius baseName = testName[testName.size - 1].split(".") 52290001Sglebius @testSuite = "test." + baseName[0] 53290001Sglebius printf "New Test: %s\n", @testSuite 54290001Sglebius end 55290001Sglebius end 56290001Sglebius 57290001Sglebius 58290001Sglebius# Test was flagged as having passed so format the output 59290001Sglebius def testPassed(array) 60290001Sglebius lastItem = array.length - 1 61290001Sglebius testName = array[lastItem - 1] 62290001Sglebius testSuiteVerify(array[@className]) 63290001Sglebius printf "%-40s PASS\n", testName 64290001Sglebius if @xmlOut == true 65290001Sglebius @arrayList.push " <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\"/>" 66290001Sglebius end 67290001Sglebius end 68290001Sglebius 69290001Sglebius# Test was flagged as being ingored so format the output 70290001Sglebius def testIgnored(array) 71290001Sglebius lastItem = array.length - 1 72290001Sglebius testName = array[lastItem - 2] 73290001Sglebius reason = array[lastItem].chomp 74290001Sglebius testSuiteVerify(array[@className]) 75290001Sglebius printf "%-40s IGNORED\n", testName 76290001Sglebius if @xmlOut == true 77290001Sglebius @arrayList.push " <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\">" 78290001Sglebius @arrayList.push " <skipped type=\"TEST IGNORED\"> " + reason + " </skipped>" 79290001Sglebius @arrayList.push " </testcase>" 80290001Sglebius end 81290001Sglebius end 82290001Sglebius 83290001Sglebius# Test was flagged as having failed so format the line 84290001Sglebius def testFailed(array) 85290001Sglebius lastItem = array.length - 1 86290001Sglebius testName = array[lastItem - 2] 87290001Sglebius reason = array[lastItem].chomp + " at line: " + array[lastItem - 3] 88290001Sglebius testSuiteVerify(array[@className]) 89290001Sglebius printf "%-40s FAILED\n", testName 90290001Sglebius if @xmlOut == true 91290001Sglebius @arrayList.push " <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\">" 92290001Sglebius @arrayList.push " <failure type=\"ASSERT FAILED\"> " + reason + " </failure>" 93290001Sglebius @arrayList.push " </testcase>" 94290001Sglebius end 95290001Sglebius end 96290001Sglebius 97290001Sglebius 98290001Sglebius# Figure out what OS we are running on. For now we are assuming if it's not Windows it must 99290001Sglebius# be Unix based. 100290001Sglebius def detectOS() 101290001Sglebius myOS = RUBY_PLATFORM.split("-") 102290001Sglebius if myOS.size == 2 103290001Sglebius if myOS[1] == "mingw32" 104290001Sglebius @className = 1 105290001Sglebius else 106290001Sglebius @className = 0 107290001Sglebius end 108290001Sglebius else 109290001Sglebius @className = 0 110290001Sglebius end 111290001Sglebius 112290001Sglebius end 113290001Sglebius 114290001Sglebius# Main function used to parse the file that was captured. 115290001Sglebius def process(name) 116290001Sglebius @testFlag = false 117290001Sglebius @arrayList = Array.new 118290001Sglebius 119290001Sglebius detectOS() 120290001Sglebius 121290001Sglebius puts "Parsing file: " + name 122290001Sglebius 123290001Sglebius 124290001Sglebius testPass = 0 125290001Sglebius testFail = 0 126290001Sglebius testIgnore = 0 127290001Sglebius puts "" 128290001Sglebius puts "=================== RESULTS =====================" 129290001Sglebius puts "" 130290001Sglebius File.open(name).each do |line| 131290001Sglebius # Typical test lines look like this: 132290001Sglebius # <path>/<test_file>.c:36:test_tc1000_opsys:FAIL: Expected 1 Was 0 133290001Sglebius # <path>/<test_file>.c:112:test_tc5004_initCanChannel:IGNORE: Not Yet Implemented 134290001Sglebius # <path>/<test_file>.c:115:test_tc5100_initCanVoidPtrs:PASS 135290001Sglebius # 136290001Sglebius # where path is different on Unix vs Windows devices (Windows leads with a drive letter) 137290001Sglebius lineArray = line.split(":") 138290001Sglebius lineSize = lineArray.size 139290001Sglebius # If we were able to split the line then we can look to see if any of our target words 140290001Sglebius # were found. Case is important. 141290001Sglebius if lineSize >= 4 142290001Sglebius # Determine if this test passed 143290001Sglebius if line.include? ":PASS" 144290001Sglebius testPassed(lineArray) 145290001Sglebius testPass += 1 146290001Sglebius elsif line.include? ":FAIL:" 147290001Sglebius testFailed(lineArray) 148290001Sglebius testFail += 1 149290001Sglebius elsif line.include? ":IGNORE:" 150290001Sglebius testIgnored(lineArray) 151290001Sglebius testIgnore += 1 152290001Sglebius # If none of the keywords are found there are no more tests for this suite so clear 153290001Sglebius # the test flag 154290001Sglebius else 155290001Sglebius @testFlag = false 156290001Sglebius end 157290001Sglebius else 158290001Sglebius @testFlag = false 159290001Sglebius end 160290001Sglebius end 161290001Sglebius puts "" 162290001Sglebius puts "=================== SUMMARY =====================" 163290001Sglebius puts "" 164290001Sglebius puts "Tests Passed : " + testPass.to_s 165290001Sglebius puts "Tests Failed : " + testFail.to_s 166290001Sglebius puts "Tests Ignored : " + testIgnore.to_s 167290001Sglebius @totalTests = testPass + testFail + testIgnore 168290001Sglebius if @xmlOut == true 169290001Sglebius heading = "<testsuite tests=\"" + @totalTests.to_s + "\" failures=\"" + testFail.to_s + "\"" + " skips=\"" + testIgnore.to_s + "\">" 170290001Sglebius @arrayList.insert(0, heading) 171290001Sglebius writeXmlOuput() 172290001Sglebius end 173290001Sglebius 174290001Sglebius # return result 175290001Sglebius end 176290001Sglebius 177290001Sglebius end 178290001Sglebius 179290001Sglebius# If the command line has no values in, used a default value of Output.txt 180290001SglebiusparseMyFile = ParseOutput.new 181290001Sglebius 182290001Sglebiusif ARGV.size >= 1 183290001Sglebius ARGV.each do |a| 184290001Sglebius if a == "-xml" 185290001Sglebius parseMyFile.setXmlOutput(); 186290001Sglebius else 187290001Sglebius parseMyFile.process(a) 188290001Sglebius break 189290001Sglebius end 190290001Sglebius end 191290001Sglebiusend 192