parseOutput.rb 7.6 KB
Newer Older
U
unknown 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
#============================================================
#  Author:   John Theofanopoulos
#  A simple parser.   Takes the output files generated during the build process and
# extracts information relating to the tests.  
#
#  Notes:
#    To capture an output file under VS builds use the following:
#      devenv [build instructions]  > Output.txt & type Output.txt
# 
#    To capture an output file under GCC/Linux builds use the following:
#      make | tee Output.txt
#
#    To use this parser use the following command
#    ruby parseOutput.rb [options] [file]
#        options:  -xml  : produce a JUnit compatible XML file
#        file      :  file to scan for results
#============================================================


class ParseOutput
# The following flag is set to true when a test is found or false otherwise.
    @testFlag
    @xmlOut
    @arrayList
    @totalTests
    @classIndex

#   Set the flag to indicate if there will be an XML output file or not  
    def setXmlOutput()
        @xmlOut = true
    end
    
#  if write our output to XML
    def writeXmlOuput()
            output = File.open("report.xml", "w")
            output << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
            @arrayList.each do |item|
                output << item << "\n"
            end
            output << "</testsuite>\n"
    end
    
#  This function will try and determine when the suite is changed.   This is
# is the name that gets added to the classname parameter.
    def  testSuiteVerify(testSuiteName)
        if @testFlag == false
            @testFlag = true;
            # Split the path name 
            testName = testSuiteName.split("/")
            # Remove the extension
            baseName = testName[testName.size - 1].split(".")
            @testSuite = "test." + baseName[0]
            printf "New Test: %s\n", @testSuite
        end
    end
    

# Test was flagged as having passed so format the output
    def testPassed(array)
        lastItem = array.length - 1
        testName = array[lastItem - 1]
        testSuiteVerify(array[@className])
        printf "%-40s PASS\n", testName
        if @xmlOut == true
            @arrayList.push "     <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\"/>"
        end          
    end
68 69 70 71 72 73 74 75 76 77 78
    
# Test was flagged as having passed so format the output.
# This is using the Unity fixture output and not the original Unity output.
    def testPassedUnityFixture(array)
        testSuite = array[0].sub("TEST(", "")
        testSuite = testSuite.sub(",", "")
        testName = array[1].sub(")", "")
        if @xmlOut == true
            @arrayList.push "     <testcase classname=\"" + testSuite + "\" name=\"" + testName + "\"/>"
        end          
    end
U
unknown 已提交
79 80 81 82 83 84 85 86

# Test was flagged as being ingored so format the output
    def testIgnored(array)
        lastItem = array.length - 1
        testName = array[lastItem - 2]
        reason = array[lastItem].chomp
        testSuiteVerify(array[@className])
        printf "%-40s IGNORED\n", testName
87 88 89 90 91 92 93 94

        if testName.start_with? "TEST("
          array2 = testName.split(" ")
          @testSuite = array2[0].sub("TEST(", "")
          @testSuite = @testSuite.sub(",", "")
          testName = array2[1].sub(")", "")
        end

U
unknown 已提交
95 96 97 98 99 100 101 102 103 104 105 106 107 108
        if @xmlOut == true
            @arrayList.push "     <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\">"
            @arrayList.push "            <skipped type=\"TEST IGNORED\"> " + reason + " </skipped>"
            @arrayList.push "     </testcase>"
        end          
    end

# Test was flagged as having failed  so format the line
    def testFailed(array)
        lastItem = array.length - 1
        testName = array[lastItem - 2]
        reason = array[lastItem].chomp + " at line: " + array[lastItem - 3]
        testSuiteVerify(array[@className])
        printf "%-40s FAILED\n", testName
109 110 111 112 113 114 115 116
        
        if testName.start_with? "TEST("
          array2 = testName.split(" ")
          @testSuite = array2[0].sub("TEST(", "")
          @testSuite = @testSuite.sub(",", "")
          testName = array2[1].sub(")", "")
        end
        
U
unknown 已提交
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
        if @xmlOut == true
            @arrayList.push "     <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\">"
            @arrayList.push "            <failure type=\"ASSERT FAILED\"> " + reason + " </failure>"
            @arrayList.push "     </testcase>"
        end          
    end

    
# Figure out what OS we are running on.   For now we are assuming if it's not Windows it must
# be Unix based.  
    def detectOS()
        myOS = RUBY_PLATFORM.split("-")
        if myOS.size == 2
            if myOS[1] == "mingw32"
                @className = 1
            else
                @className = 0
            end
E
Eivind Tagseth 已提交
135 136
	else
                @className = 0
U
unknown 已提交
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
        end
        
    end

# Main function used to parse the file that was captured.
    def process(name)
        @testFlag = false
        @arrayList = Array.new

        detectOS()

        puts "Parsing file: " + name
    
      
        testPass = 0
        testFail = 0
        testIgnore = 0
        puts ""
        puts "=================== RESULTS ====================="
        puts ""
        File.open(name).each do |line|
        # Typical test lines look like this:
        # <path>/<test_file>.c:36:test_tc1000_opsys:FAIL: Expected 1 Was 0
        # <path>/<test_file>.c:112:test_tc5004_initCanChannel:IGNORE: Not Yet Implemented
        # <path>/<test_file>.c:115:test_tc5100_initCanVoidPtrs:PASS
        #
        # where path is different on Unix vs Windows devices (Windows leads with a drive letter)
            lineArray = line.split(":")
            lineSize = lineArray.size
            # If we were able to split the line then we can look to see if any of our target words
            # were found.  Case is important.
168
            if ((lineSize >= 4) || (line.start_with? "TEST("))
U
unknown 已提交
169 170 171 172 173 174 175 176 177 178
                # Determine if this test passed
                if  line.include? ":PASS"
                    testPassed(lineArray)
                    testPass += 1
                elsif line.include? ":FAIL:"
                    testFailed(lineArray)
                    testFail += 1
                elsif line.include? ":IGNORE:"
                    testIgnored(lineArray)
                    testIgnore += 1
179 180 181 182 183 184
                elsif line.start_with? "TEST("
                  if line.include? " PASS"
                    lineArray = line.split(" ")
                    testPassedUnityFixture(lineArray)
                    testPass += 1
                  end
U
unknown 已提交
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
                # If none of the keywords are found there are no more tests for this suite so clear
                # the test flag
                else
                    @testFlag = false
                end
            else
                @testFlag = false
                end
            end
        puts ""
        puts "=================== SUMMARY ====================="
        puts ""
        puts "Tests Passed  : " + testPass.to_s
        puts "Tests Failed  : " + testFail.to_s
        puts "Tests Ignored : " + testIgnore.to_s
        @totalTests = testPass + testFail + testIgnore
        if @xmlOut == true
            heading = "<testsuite tests=\"" +  @totalTests.to_s  + "\" failures=\"" + testFail.to_s + "\""  + " skips=\"" +  testIgnore.to_s + "\">" 
            @arrayList.insert(0, heading) 
            writeXmlOuput()
        end

    #  return result
    end

 end

# If the command line has no values in, used a default value of Output.txt
parseMyFile = ParseOutput.new

if ARGV.size >= 1 
    ARGV.each do |a|
        if a == "-xml"
            parseMyFile.setXmlOutput();
        else
            parseMyFile.process(a)
            break
        end
    end
end