parseOutput.rb 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #============================================================
  2. # Author: John Theofanopoulos
  3. # A simple parser. Takes the output files generated during the build process and
  4. # extracts information relating to the tests.
  5. #
  6. # Notes:
  7. # To capture an output file under VS builds use the following:
  8. # devenv [build instructions] > Output.txt & type Output.txt
  9. #
  10. # To capture an output file under GCC/Linux builds use the following:
  11. # make | tee Output.txt
  12. #
  13. # To use this parser use the following command
  14. # ruby parseOutput.rb [options] [file]
  15. # options: -xml : produce a JUnit compatible XML file
  16. # file : file to scan for results
  17. #============================================================
  18. class ParseOutput
  19. # The following flag is set to true when a test is found or false otherwise.
  20. @testFlag
  21. @xmlOut
  22. @arrayList
  23. @totalTests
  24. @classIndex
  25. # Set the flag to indicate if there will be an XML output file or not
  26. def setXmlOutput()
  27. @xmlOut = true
  28. end
  29. # if write our output to XML
  30. def writeXmlOuput()
  31. output = File.open("report.xml", "w")
  32. output << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
  33. @arrayList.each do |item|
  34. output << item << "\n"
  35. end
  36. output << "</testsuite>\n"
  37. end
  38. # This function will try and determine when the suite is changed. This is
  39. # is the name that gets added to the classname parameter.
  40. def testSuiteVerify(testSuiteName)
  41. if @testFlag == false
  42. @testFlag = true;
  43. # Split the path name
  44. testName = testSuiteName.split("/")
  45. # Remove the extension
  46. baseName = testName[testName.size - 1].split(".")
  47. @testSuite = "test." + baseName[0]
  48. printf "New Test: %s\n", @testSuite
  49. end
  50. end
  51. # Test was flagged as having passed so format the output
  52. def testPassed(array)
  53. lastItem = array.length - 1
  54. testName = array[lastItem - 1]
  55. testSuiteVerify(array[@className])
  56. printf "%-40s PASS\n", testName
  57. if @xmlOut == true
  58. @arrayList.push " <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\"/>"
  59. end
  60. end
  61. # Test was flagged as being ingored so format the output
  62. def testIgnored(array)
  63. lastItem = array.length - 1
  64. testName = array[lastItem - 2]
  65. reason = array[lastItem].chomp
  66. testSuiteVerify(array[@className])
  67. printf "%-40s IGNORED\n", testName
  68. if @xmlOut == true
  69. @arrayList.push " <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\">"
  70. @arrayList.push " <skipped type=\"TEST IGNORED\"> " + reason + " </skipped>"
  71. @arrayList.push " </testcase>"
  72. end
  73. end
  74. # Test was flagged as having failed so format the line
  75. def testFailed(array)
  76. lastItem = array.length - 1
  77. testName = array[lastItem - 2]
  78. reason = array[lastItem].chomp + " at line: " + array[lastItem - 3]
  79. testSuiteVerify(array[@className])
  80. printf "%-40s FAILED\n", testName
  81. if @xmlOut == true
  82. @arrayList.push " <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\">"
  83. @arrayList.push " <failure type=\"ASSERT FAILED\"> " + reason + " </failure>"
  84. @arrayList.push " </testcase>"
  85. end
  86. end
  87. # Figure out what OS we are running on. For now we are assuming if it's not Windows it must
  88. # be Unix based.
  89. def detectOS()
  90. myOS = RUBY_PLATFORM.split("-")
  91. if myOS.size == 2
  92. if myOS[1] == "mingw32"
  93. @className = 1
  94. else
  95. @className = 0
  96. end
  97. else
  98. @className = 0
  99. end
  100. end
  101. # Main function used to parse the file that was captured.
  102. def process(name)
  103. @testFlag = false
  104. @arrayList = Array.new
  105. detectOS()
  106. puts "Parsing file: " + name
  107. testPass = 0
  108. testFail = 0
  109. testIgnore = 0
  110. puts ""
  111. puts "=================== RESULTS ====================="
  112. puts ""
  113. File.open(name).each do |line|
  114. # Typical test lines look like this:
  115. # <path>/<test_file>.c:36:test_tc1000_opsys:FAIL: Expected 1 Was 0
  116. # <path>/<test_file>.c:112:test_tc5004_initCanChannel:IGNORE: Not Yet Implemented
  117. # <path>/<test_file>.c:115:test_tc5100_initCanVoidPtrs:PASS
  118. #
  119. # where path is different on Unix vs Windows devices (Windows leads with a drive letter)
  120. lineArray = line.split(":")
  121. lineSize = lineArray.size
  122. # If we were able to split the line then we can look to see if any of our target words
  123. # were found. Case is important.
  124. if lineSize >= 4
  125. # Determine if this test passed
  126. if line.include? ":PASS"
  127. testPassed(lineArray)
  128. testPass += 1
  129. elsif line.include? ":FAIL:"
  130. testFailed(lineArray)
  131. testFail += 1
  132. elsif line.include? ":IGNORE:"
  133. testIgnored(lineArray)
  134. testIgnore += 1
  135. # If none of the keywords are found there are no more tests for this suite so clear
  136. # the test flag
  137. else
  138. @testFlag = false
  139. end
  140. else
  141. @testFlag = false
  142. end
  143. end
  144. puts ""
  145. puts "=================== SUMMARY ====================="
  146. puts ""
  147. puts "Tests Passed : " + testPass.to_s
  148. puts "Tests Failed : " + testFail.to_s
  149. puts "Tests Ignored : " + testIgnore.to_s
  150. @totalTests = testPass + testFail + testIgnore
  151. if @xmlOut == true
  152. heading = "<testsuite tests=\"" + @totalTests.to_s + "\" failures=\"" + testFail.to_s + "\"" + " skips=\"" + testIgnore.to_s + "\">"
  153. @arrayList.insert(0, heading)
  154. writeXmlOuput()
  155. end
  156. # return result
  157. end
  158. end
  159. # If the command line has no values in, used a default value of Output.txt
  160. parseMyFile = ParseOutput.new
  161. if ARGV.size >= 1
  162. ARGV.each do |a|
  163. if a == "-xml"
  164. parseMyFile.setXmlOutput();
  165. else
  166. parseMyFile.process(a)
  167. break
  168. end
  169. end
  170. end