1289715Sglebius#============================================================ 2289715Sglebius# Author: John Theofanopoulos 3289715Sglebius# A simple parser. Takes the output files generated during the build process and 4289715Sglebius# extracts information relating to the tests. 5289715Sglebius# 6289715Sglebius# Notes: 7289715Sglebius# To capture an output file under VS builds use the following: 8289715Sglebius# devenv [build instructions] > Output.txt & type Output.txt 9289715Sglebius# 10289715Sglebius# To capture an output file under GCC/Linux builds use the following: 11289715Sglebius# make | tee Output.txt 12289715Sglebius# 13289715Sglebius# To use this parser use the following command 14289715Sglebius# ruby parseOutput.rb [options] [file] 15289715Sglebius# options: -xml : produce a JUnit compatible XML file 16289715Sglebius# file : file to scan for results 17289715Sglebius#============================================================ 18289715Sglebius 19289715Sglebius 20289715Sglebiusclass ParseOutput 21289715Sglebius# The following flag is set to true when a test is found or false otherwise. 22289715Sglebius @testFlag 23289715Sglebius @xmlOut 24289715Sglebius @arrayList 25289715Sglebius @totalTests 26289715Sglebius @classIndex 27289715Sglebius 28289715Sglebius# Set the flag to indicate if there will be an XML output file or not 29289715Sglebius def setXmlOutput() 30289715Sglebius @xmlOut = true 31289715Sglebius end 32289715Sglebius 33289715Sglebius# if write our output to XML 34289715Sglebius def writeXmlOuput() 35289715Sglebius output = File.open("report.xml", "w") 36289715Sglebius output << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" 37289715Sglebius @arrayList.each do |item| 38289715Sglebius output << item << "\n" 39289715Sglebius end 40289715Sglebius output << "</testsuite>\n" 41289715Sglebius end 42289715Sglebius 43289715Sglebius# This function will try and determine when the suite is changed. This is 44289715Sglebius# is the name that gets added to the classname parameter. 45289715Sglebius def testSuiteVerify(testSuiteName) 46289715Sglebius if @testFlag == false 47289715Sglebius @testFlag = true; 48289715Sglebius # Split the path name 49289715Sglebius testName = testSuiteName.split("/") 50289715Sglebius # Remove the extension 51289715Sglebius baseName = testName[testName.size - 1].split(".") 52289715Sglebius @testSuite = "test." + baseName[0] 53289715Sglebius printf "New Test: %s\n", @testSuite 54289715Sglebius end 55289715Sglebius end 56289715Sglebius 57289715Sglebius 58289715Sglebius# Test was flagged as having passed so format the output 59289715Sglebius def testPassed(array) 60289715Sglebius lastItem = array.length - 1 61289715Sglebius testName = array[lastItem - 1] 62289715Sglebius testSuiteVerify(array[@className]) 63289715Sglebius printf "%-40s PASS\n", testName 64289715Sglebius if @xmlOut == true 65289715Sglebius @arrayList.push " <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\"/>" 66289715Sglebius end 67289715Sglebius end 68289715Sglebius 69289715Sglebius# Test was flagged as being ingored so format the output 70289715Sglebius def testIgnored(array) 71289715Sglebius lastItem = array.length - 1 72289715Sglebius testName = array[lastItem - 2] 73289715Sglebius reason = array[lastItem].chomp 74289715Sglebius testSuiteVerify(array[@className]) 75289715Sglebius printf "%-40s IGNORED\n", testName 76289715Sglebius if @xmlOut == true 77289715Sglebius @arrayList.push " <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\">" 78289715Sglebius @arrayList.push " <skipped type=\"TEST IGNORED\"> " + reason + " </skipped>" 79289715Sglebius @arrayList.push " </testcase>" 80289715Sglebius end 81289715Sglebius end 82289715Sglebius 83289715Sglebius# Test was flagged as having failed so format the line 84289715Sglebius def testFailed(array) 85289715Sglebius lastItem = array.length - 1 86289715Sglebius testName = array[lastItem - 2] 87289715Sglebius reason = array[lastItem].chomp + " at line: " + array[lastItem - 3] 88289715Sglebius testSuiteVerify(array[@className]) 89289715Sglebius printf "%-40s FAILED\n", testName 90289715Sglebius if @xmlOut == true 91289715Sglebius @arrayList.push " <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\">" 92289715Sglebius @arrayList.push " <failure type=\"ASSERT FAILED\"> " + reason + " </failure>" 93289715Sglebius @arrayList.push " </testcase>" 94289715Sglebius end 95289715Sglebius end 96289715Sglebius 97289715Sglebius 98289715Sglebius# Figure out what OS we are running on. For now we are assuming if it's not Windows it must 99289715Sglebius# be Unix based. 100289715Sglebius def detectOS() 101289715Sglebius myOS = RUBY_PLATFORM.split("-") 102289715Sglebius if myOS.size == 2 103289715Sglebius if myOS[1] == "mingw32" 104289715Sglebius @className = 1 105289715Sglebius else 106289715Sglebius @className = 0 107289715Sglebius end 108289715Sglebius else 109289715Sglebius @className = 0 110289715Sglebius end 111289715Sglebius 112289715Sglebius end 113289715Sglebius 114289715Sglebius# Main function used to parse the file that was captured. 115289715Sglebius def process(name) 116289715Sglebius @testFlag = false 117289715Sglebius @arrayList = Array.new 118289715Sglebius 119289715Sglebius detectOS() 120289715Sglebius 121289715Sglebius puts "Parsing file: " + name 122289715Sglebius 123289715Sglebius 124289715Sglebius testPass = 0 125289715Sglebius testFail = 0 126289715Sglebius testIgnore = 0 127289715Sglebius puts "" 128289715Sglebius puts "=================== RESULTS =====================" 129289715Sglebius puts "" 130289715Sglebius File.open(name).each do |line| 131289715Sglebius # Typical test lines look like this: 132289715Sglebius # <path>/<test_file>.c:36:test_tc1000_opsys:FAIL: Expected 1 Was 0 133289715Sglebius # <path>/<test_file>.c:112:test_tc5004_initCanChannel:IGNORE: Not Yet Implemented 134289715Sglebius # <path>/<test_file>.c:115:test_tc5100_initCanVoidPtrs:PASS 135289715Sglebius # 136289715Sglebius # where path is different on Unix vs Windows devices (Windows leads with a drive letter) 137289715Sglebius lineArray = line.split(":") 138289715Sglebius lineSize = lineArray.size 139289715Sglebius # If we were able to split the line then we can look to see if any of our target words 140289715Sglebius # were found. Case is important. 141289715Sglebius if lineSize >= 4 142289715Sglebius # Determine if this test passed 143289715Sglebius if line.include? ":PASS" 144289715Sglebius testPassed(lineArray) 145289715Sglebius testPass += 1 146289715Sglebius elsif line.include? ":FAIL:" 147289715Sglebius testFailed(lineArray) 148289715Sglebius testFail += 1 149289715Sglebius elsif line.include? ":IGNORE:" 150289715Sglebius testIgnored(lineArray) 151289715Sglebius testIgnore += 1 152289715Sglebius # If none of the keywords are found there are no more tests for this suite so clear 153289715Sglebius # the test flag 154289715Sglebius else 155289715Sglebius @testFlag = false 156289715Sglebius end 157289715Sglebius else 158289715Sglebius @testFlag = false 159289715Sglebius end 160289715Sglebius end 161289715Sglebius puts "" 162289715Sglebius puts "=================== SUMMARY =====================" 163289715Sglebius puts "" 164289715Sglebius puts "Tests Passed : " + testPass.to_s 165289715Sglebius puts "Tests Failed : " + testFail.to_s 166289715Sglebius puts "Tests Ignored : " + testIgnore.to_s 167289715Sglebius @totalTests = testPass + testFail + testIgnore 168289715Sglebius if @xmlOut == true 169289715Sglebius heading = "<testsuite tests=\"" + @totalTests.to_s + "\" failures=\"" + testFail.to_s + "\"" + " skips=\"" + testIgnore.to_s + "\">" 170289715Sglebius @arrayList.insert(0, heading) 171289715Sglebius writeXmlOuput() 172289715Sglebius end 173289715Sglebius 174289715Sglebius # return result 175289715Sglebius end 176289715Sglebius 177289715Sglebius end 178289715Sglebius 179289715Sglebius# If the command line has no values in, used a default value of Output.txt 180289715SglebiusparseMyFile = ParseOutput.new 181289715Sglebius 182289715Sglebiusif ARGV.size >= 1 183289715Sglebius ARGV.each do |a| 184289715Sglebius if a == "-xml" 185289715Sglebius parseMyFile.setXmlOutput(); 186289715Sglebius else 187289715Sglebius parseMyFile.process(a) 188289715Sglebius break 189289715Sglebius end 190289715Sglebius end 191289715Sglebiusend 192