From 0937bf728caed9503e2b5aae306036f9bb68e088 Mon Sep 17 00:00:00 2001
From: Fabian Zahn <fabian.zahn@gmail.com>
Date: Thu, 22 Feb 2018 19:55:40 +0100
Subject: [PATCH 1/5] - Removed member variable @test_flag - Fixed stdout
 output if fixture is active - Refactored the state manipulation of
 @test_suite and moved it completely into test_suite_verify()

---
 auto/parse_output.rb | 61 ++++++++++++++++++++++++--------------------
 1 file changed, 34 insertions(+), 27 deletions(-)

diff --git a/auto/parse_output.rb b/auto/parse_output.rb
index b5132a0..33d1f71 100644
--- a/auto/parse_output.rb
+++ b/auto/parse_output.rb
@@ -18,11 +18,11 @@
 
 class ParseOutput
   def initialize
-    @test_flag = false
     @xml_out = false
     @array_list = false
+    @class_name = 0
+    @test_suite = nil
     @total_tests = false
-    @class_index = false
   end
 
   #   Set the flag to indicate if there will be an XML output file or not
@@ -30,7 +30,7 @@ class ParseOutput
     @xml_out = true
   end
 
-  #  if write our output to XML
+  #  If write our output to XML
   def write_xml_output
     output = File.open('report.xml', 'w')
     output << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
@@ -40,12 +40,10 @@ class ParseOutput
     output << "</testsuite>\n"
   end
 
-  #  This function will try and determine when the suite is changed.   This is
+  # This function will try and determine when the suite is changed. This is
   # is the name that gets added to the classname parameter.
   def test_suite_verify(test_suite_name)
-    return if @test_flag
 
-    @test_flag = true
     # Split the path name
     test_name = if @class_name == 1
                   test_suite_name.split('\\') # Windows
@@ -53,10 +51,15 @@ class ParseOutput
                   test_suite_name.split('/')  # Unix based
                 end
 
-    # Remove the extension
-    base_name = test_name[test_name.size - 1].split('.')
-    @test_suite = 'test.' + base_name[0]
-    printf "New Test: %s\n", @test_suite
+    # Remove the extension and extract the base_name
+    base_name = test_name[test_name.size - 1].split('.')[0]
+
+    # Is this a new test suite?
+    if base_name.to_s != @test_suite.to_s
+      @test_suite = base_name
+      printf "New Test: %s\n", @test_suite
+    end
+
   end
 
   # Test was flagged as having passed so format the output
@@ -77,7 +80,8 @@ class ParseOutput
     test_suite = array[0].sub('TEST(', '')
     test_suite = test_suite.sub(',', '')
     test_name = array[1].sub(')', '')
-
+    test_suite_verify(array[@class_name])
+    printf "%-40s PASS\n", test_name
     return unless @xml_out
 
     @array_list.push '     <testcase classname="' + test_suite + '" name="' + test_name + '"/>'
@@ -88,16 +92,21 @@ class ParseOutput
     last_item = array.length - 1
     test_name = array[last_item - 2]
     reason = array[last_item].chomp.lstrip
-    test_suite_verify(array[@class_name])
-    printf "%-40s IGNORED\n", test_name
+    class_name = array[@class_name]
 
     if test_name.start_with? 'TEST('
       array2 = test_name.split(' ')
-      @test_suite = array2[0].sub('TEST(', '')
-      @test_suite = @test_suite.sub(',', '')
+
+      test_suite = array2[0].sub('TEST(', '')
+      test_suite = test_suite.sub(',', '')
+      class_name = test_suite
+
       test_name = array2[1].sub(')', '')
     end
 
+    test_suite_verify(class_name)
+    printf "%-40s IGNORED\n", test_name
+
     return unless @xml_out
 
     @array_list.push '     <testcase classname="' + @test_suite + '" name="' + test_name + '">'
@@ -110,16 +119,21 @@ class ParseOutput
     last_item = array.length - 1
     test_name = array[last_item - 2]
     reason = array[last_item].chomp.lstrip + ' at line: ' + array[last_item - 3]
-    test_suite_verify(array[@class_name])
-    printf "%-40s FAILED\n", test_name
+    class_name = array[@class_name]
 
     if test_name.start_with? 'TEST('
       array2 = test_name.split(' ')
-      @test_suite = array2[0].sub('TEST(', '')
-      @test_suite = @test_suite.sub(',', '')
+
+      test_suite = array2[0].sub('TEST(', '')
+      test_suite = test_suite.sub(',', '')
+      class_name = test_suite
+
       test_name = array2[1].sub(')', '')
     end
 
+    test_suite_verify(class_name)
+    printf "%-40s FAILED\n", test_name
+
     return unless @xml_out
 
     @array_list.push '     <testcase classname="' + @test_suite + '" name="' + test_name + '">'
@@ -144,7 +158,6 @@ class ParseOutput
 
   # Main function used to parse the file that was captured.
   def process(name)
-    @test_flag = false
     @array_list = []
 
     detect_os
@@ -189,13 +202,7 @@ class ParseOutput
             test_passed_unity_fixture(line_array)
             test_pass += 1
           end
-        # If none of the keywords are found there are no more tests for this suite so clear
-        # the test flag
-        else
-          @test_flag = false
         end
-      else
-        @test_flag = false
       end
     end
     puts ''
@@ -208,7 +215,7 @@ class ParseOutput
 
     return unless @xml_out
 
-    heading = '<testsuite name="' + @test_suite.to_s + '" tests="' + @total_tests.to_s + '" failures="' + test_fail.to_s + '"' + ' skips="' + test_ignore.to_s + '">'
+    heading = '<testsuite name="Unity" tests="' + @total_tests.to_s + '" failures="' + test_fail.to_s + '"' + ' skips="' + test_ignore.to_s + '">'
     @array_list.insert(0, heading)
     write_xml_output
   end

From ea51e2b35cb10fad3cbdc101142543daf96ea80f Mon Sep 17 00:00:00 2001
From: Fabian Zahn <fabian.zahn@gmail.com>
Date: Thu, 22 Feb 2018 21:21:32 +0100
Subject: [PATCH 2/5] Refactored the os specific settings, it is now possible
 to convert both styles on every system (and even mixed)

---
 auto/parse_output.rb | 36 +++++++++++++++---------------------
 1 file changed, 15 insertions(+), 21 deletions(-)

diff --git a/auto/parse_output.rb b/auto/parse_output.rb
index 33d1f71..02adbdc 100644
--- a/auto/parse_output.rb
+++ b/auto/parse_output.rb
@@ -23,6 +23,7 @@ class ParseOutput
     @class_name = 0
     @test_suite = nil
     @total_tests = false
+    @path_delim = nil
   end
 
   #   Set the flag to indicate if there will be an XML output file or not
@@ -45,11 +46,7 @@ class ParseOutput
   def test_suite_verify(test_suite_name)
 
     # Split the path name
-    test_name = if @class_name == 1
-                  test_suite_name.split('\\') # Windows
-                else
-                  test_suite_name.split('/')  # Unix based
-                end
+    test_name = test_suite_name.split(@path_delim)
 
     # Remove the extension and extract the base_name
     base_name = test_name[test_name.size - 1].split('.')[0]
@@ -59,7 +56,6 @@ class ParseOutput
       @test_suite = base_name
       printf "New Test: %s\n", @test_suite
     end
-
   end
 
   # Test was flagged as having passed so format the output
@@ -141,27 +137,24 @@ class ParseOutput
     @array_list.push '     </testcase>'
   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 detect_os
-    os = RUBY_PLATFORM.split('-')
-    @class_name = if os.size == 2
-                    if os[1] == 'mingw32'
-                      1
-                    else
-                      0
-                    end
-                  else
-                    0
-                  end
+  # Adjusts the os specific members according to the current path style
+  # (Windows or Unix based)
+  def set_os_specifics(line)
+    if line.include? '\\'
+      # Windows X:\Y\Z
+      @class_name = 1
+      @path_delim = '\\'
+    else
+      # Unix Based /X/Y/Z
+      @class_name = 0
+      @path_delim = '/'
+    end
   end
 
   # Main function used to parse the file that was captured.
   def process(name)
     @array_list = []
 
-    detect_os
-
     puts 'Parsing file: ' + name
 
     test_pass = 0
@@ -177,6 +170,7 @@ class ParseOutput
       # <path>/<test_file>.c:115:test_tc5100_initCanVoidPtrs:PASS
       #
       # where path is different on Unix vs Windows devices (Windows leads with a drive letter)
+      set_os_specifics(line)
       line_array = line.split(':')
 
       # If we were able to split the line then we can look to see if any of our target words

From 7a437665864a99320e88606bb6e901a64bc763da Mon Sep 17 00:00:00 2001
From: Fabian Zahn <fabian.zahn@gmail.com>
Date: Thu, 22 Feb 2018 21:33:11 +0100
Subject: [PATCH 3/5] - Fixed whitespaces and formatting - Added more
 expressiveness to the code - Fixed some of the rubocop hints

---
 auto/parse_output.rb | 37 +++++++++++++++++++------------------
 1 file changed, 19 insertions(+), 18 deletions(-)

diff --git a/auto/parse_output.rb b/auto/parse_output.rb
index 02adbdc..edb69fb 100644
--- a/auto/parse_output.rb
+++ b/auto/parse_output.rb
@@ -1,21 +1,22 @@
 #============================================================
 #  Author:   John Theofanopoulos
-#  A simple parser.   Takes the output files generated during the build process and
-# extracts information relating to the tests.
+#  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:
+#    To capture an output file under 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
+#        file:  file to scan for results
 #============================================================
 
+# Parser class for handling the input file
 class ParseOutput
   def initialize
     @xml_out = false
@@ -26,12 +27,12 @@ class ParseOutput
     @path_delim = nil
   end
 
-  #   Set the flag to indicate if there will be an XML output file or not
+  # Set the flag to indicate if there will be an XML output file or not
   def set_xml_output
     @xml_out = true
   end
 
-  #  If write our output to XML
+  # If write our output to XML
   def write_xml_output
     output = File.open('report.xml', 'w')
     output << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
@@ -44,18 +45,17 @@ class ParseOutput
   # This function will try and determine when the suite is changed. This is
   # is the name that gets added to the classname parameter.
   def test_suite_verify(test_suite_name)
-
     # Split the path name
     test_name = test_suite_name.split(@path_delim)
 
     # Remove the extension and extract the base_name
     base_name = test_name[test_name.size - 1].split('.')[0]
 
-    # Is this a new test suite?
-    if base_name.to_s != @test_suite.to_s
-      @test_suite = base_name
-      printf "New Test: %s\n", @test_suite
-    end
+    # Return if the test suite hasn't changed
+    return unless base_name.to_s != @test_suite.to_s
+
+    @test_suite = base_name
+    printf "New Test: %s\n", @test_suite
   end
 
   # Test was flagged as having passed so format the output
@@ -78,6 +78,7 @@ class ParseOutput
     test_name = array[1].sub(')', '')
     test_suite_verify(array[@class_name])
     printf "%-40s PASS\n", test_name
+
     return unless @xml_out
 
     @array_list.push '     <testcase classname="' + test_suite + '" name="' + test_name + '"/>'
@@ -152,10 +153,10 @@ class ParseOutput
   end
 
   # Main function used to parse the file that was captured.
-  def process(name)
+  def process(file_name)
     @array_list = []
 
-    puts 'Parsing file: ' + name
+    puts 'Parsing file: ' + file_name
 
     test_pass = 0
     test_fail = 0
@@ -163,7 +164,7 @@ class ParseOutput
     puts ''
     puts '=================== RESULTS ====================='
     puts ''
-    File.open(name).each do |line|
+    File.open(file_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
@@ -219,11 +220,11 @@ end
 parse_my_file = ParseOutput.new
 
 if ARGV.size >= 1
-  ARGV.each do |a|
-    if a == '-xml'
+  ARGV.each do |arg|
+    if arg == '-xml'
       parse_my_file.set_xml_output
     else
-      parse_my_file.process(a)
+      parse_my_file.process(arg)
       break
     end
   end

From 1994bf9d68d792ece33f2750d62bb7c361f12ed8 Mon Sep 17 00:00:00 2001
From: Fabian Zahn <fabian.zahn@gmail.com>
Date: Mon, 26 Feb 2018 22:13:29 +0100
Subject: [PATCH 4/5] Fixed unity fixture output and added methods for each of
 the different outputs. Added documentation. Fixed some whitespaces.
 Refactored class_name to class_name_idx (expressiveness). Refactored the xml
 output to methods (extensibility).

---
 auto/parse_output.rb | 238 ++++++++++++++++++++++++++++---------------
 1 file changed, 156 insertions(+), 82 deletions(-)

diff --git a/auto/parse_output.rb b/auto/parse_output.rb
index edb69fb..cbafd7c 100644
--- a/auto/parse_output.rb
+++ b/auto/parse_output.rb
@@ -1,30 +1,38 @@
 #============================================================
-#  Author:   John Theofanopoulos
-#  A simple parser.  Takes the output files generated during the
+#  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
+#      devenv [build instructions] > Output.txt & type Output.txt
 #
 #    To capture an output file under 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
+#        options: -xml  : produce a JUnit compatible XML file
+#           file: file to scan for results
 #============================================================
 
 # Parser class for handling the input file
 class ParseOutput
   def initialize
+    # internal data
+    @class_name_idx = 0
+    @path_delim = nil
+
+    # xml output related
     @xml_out = false
     @array_list = false
-    @class_name = 0
+
+    # current suite name and statistics
     @test_suite = nil
-    @total_tests = false
-    @path_delim = nil
+    @total_tests  = 0
+    @test_passed  = 0
+    @test_failed  = 0
+    @test_ignored = 0
   end
 
   # Set the flag to indicate if there will be an XML output file or not
@@ -39,7 +47,34 @@ class ParseOutput
     @array_list.each do |item|
       output << item << "\n"
     end
-    output << "</testsuite>\n"
+  end
+
+  # Pushes the suite info as xml to the array list, which will be written later
+  def push_xml_output_suite_info
+    # Insert opening tag at front
+    heading = '<testsuite name="Unity" tests="' + @total_tests.to_s + '" failures="' + @test_failed.to_s + '"' + ' skips="' + @test_ignored.to_s + '">'
+    @array_list.insert(0, heading)
+    # Push back the closing tag
+    @array_list.push '</testsuite>'
+  end
+
+  # Pushes xml output data to the array list, which will be written later
+  def push_xml_output_passed(test_name)
+    @array_list.push '    <testcase classname="' + @test_suite + '" name="' + test_name + '"/>'
+  end
+
+  # Pushes xml output data to the array list, which will be written later
+  def push_xml_output_failed(test_name, reason)
+    @array_list.push '    <testcase classname="' + @test_suite + '" name="' + test_name + '">'
+    @array_list.push '        <failure type="ASSERT FAILED">' + reason + '</failure>'
+    @array_list.push '    </testcase>'
+  end
+
+  # Pushes xml output data to the array list, which will be written later
+  def push_xml_output_ignored(test_name, reason)
+    @array_list.push '    <testcase classname="' + @test_suite + '" name="' + test_name + '">'
+    @array_list.push '        <skipped type="TEST IGNORED">' + reason + '</skipped>'
+    @array_list.push '    </testcase>'
   end
 
   # This function will try and determine when the suite is changed. This is
@@ -58,65 +93,76 @@ class ParseOutput
     printf "New Test: %s\n", @test_suite
   end
 
-  # Test was flagged as having passed so format the output
-  def test_passed(array)
-    last_item = array.length - 1
-    test_name = array[last_item - 1]
-    test_suite_verify(array[@class_name])
-    printf "%-40s PASS\n", test_name
-
-    return unless @xml_out
-
-    @array_list.push '     <testcase classname="' + @test_suite + '" name="' + test_name + '"/>'
+  # Prepares the line for verbose fixture output ("-v")
+  def prepare_fixture_line(line)
+    line = line.sub('IGNORE_TEST(', '')
+    line = line.sub('TEST(', '')
+    line = line.sub(')', ',')
+    line = line.chomp
+    array = line.split(',')
+    array.map { |x| x.to_s.lstrip.chomp }
   end
 
   # Test was flagged as having passed so format the output.
   # This is using the Unity fixture output and not the original Unity output.
   def test_passed_unity_fixture(array)
-    test_suite = array[0].sub('TEST(', '')
-    test_suite = test_suite.sub(',', '')
-    test_name = array[1].sub(')', '')
-    test_suite_verify(array[@class_name])
+    class_name = array[0]
+    test_name  = array[1]
+    test_suite_verify(class_name)
+    printf "%-40s PASS\n", test_name
+
+    push_xml_output_passed(test_name) if @xml_out
+  end
+
+  # Test was flagged as having failed so format the output.
+  # This is using the Unity fixture output and not the original Unity output.
+  def test_failed_unity_fixture(array)
+    class_name = array[0]
+    test_name  = array[1]
+    test_suite_verify(class_name)
+    reason_array = array[2].split(':')
+    reason = reason_array[-1].lstrip.chomp + ' at line: ' + reason_array[-4]
+
+    printf "%-40s FAILED\n", test_name
+
+    push_xml_output_failed(test_name, reason) if @xml_out
+  end
+
+  # Test was flagged as being ignored so format the output.
+  # This is using the Unity fixture output and not the original Unity output.
+  def test_ignored_unity_fixture(array)
+    class_name = array[0]
+    test_name  = array[1]
+    reason = 'No reason given'
+    if array.size > 2
+      reason_array = array[2].split(':')
+      tmp_reason = reason_array[-1].lstrip.chomp
+      reason = tmp_reason == 'IGNORE' ? 'No reason given' : tmp_reason
+    end
+    test_suite_verify(class_name)
+    printf "%-40s IGNORED\n", test_name
+
+    push_xml_output_ignored(test_name, reason) if @xml_out
+  end
+
+  # Test was flagged as having passed so format the output
+  def test_passed(array)
+    last_item = array.length - 1
+    test_name = array[last_item - 1]
+    test_suite_verify(array[@class_name_idx])
     printf "%-40s PASS\n", test_name
 
     return unless @xml_out
 
-    @array_list.push '     <testcase classname="' + test_suite + '" name="' + test_name + '"/>'
+    push_xml_output_passed(test_name) if @xml_out
   end
 
-  # Test was flagged as being ignored so format the output
-  def test_ignored(array)
-    last_item = array.length - 1
-    test_name = array[last_item - 2]
-    reason = array[last_item].chomp.lstrip
-    class_name = array[@class_name]
-
-    if test_name.start_with? 'TEST('
-      array2 = test_name.split(' ')
-
-      test_suite = array2[0].sub('TEST(', '')
-      test_suite = test_suite.sub(',', '')
-      class_name = test_suite
-
-      test_name = array2[1].sub(')', '')
-    end
-
-    test_suite_verify(class_name)
-    printf "%-40s IGNORED\n", test_name
-
-    return unless @xml_out
-
-    @array_list.push '     <testcase classname="' + @test_suite + '" name="' + test_name + '">'
-    @array_list.push '            <skipped type="TEST IGNORED">' + reason + '</skipped>'
-    @array_list.push '     </testcase>'
-  end
-
-  # Test was flagged as having failed  so format the line
+  # Test was flagged as having failed so format the line
   def test_failed(array)
     last_item = array.length - 1
     test_name = array[last_item - 2]
     reason = array[last_item].chomp.lstrip + ' at line: ' + array[last_item - 3]
-    class_name = array[@class_name]
+    class_name = array[@class_name_idx]
 
     if test_name.start_with? 'TEST('
       array2 = test_name.split(' ')
@@ -131,11 +177,30 @@ class ParseOutput
     test_suite_verify(class_name)
     printf "%-40s FAILED\n", test_name
 
-    return unless @xml_out
+    push_xml_output_failed(test_name, reason) if @xml_out
+  end
 
-    @array_list.push '     <testcase classname="' + @test_suite + '" name="' + test_name + '">'
-    @array_list.push '            <failure type="ASSERT FAILED">' + reason + '</failure>'
-    @array_list.push '     </testcase>'
+  # Test was flagged as being ignored so format the output
+  def test_ignored(array)
+    last_item = array.length - 1
+    test_name = array[last_item - 2]
+    reason = array[last_item].chomp.lstrip
+    class_name = array[@class_name_idx]
+
+    if test_name.start_with? 'TEST('
+      array2 = test_name.split(' ')
+
+      test_suite = array2[0].sub('TEST(', '')
+      test_suite = test_suite.sub(',', '')
+      class_name = test_suite
+
+      test_name = array2[1].sub(')', '')
+    end
+
+    test_suite_verify(class_name)
+    printf "%-40s IGNORED\n", test_name
+
+    push_xml_output_ignored(test_name, reason) if @xml_out
   end
 
   # Adjusts the os specific members according to the current path style
@@ -143,11 +208,11 @@ class ParseOutput
   def set_os_specifics(line)
     if line.include? '\\'
       # Windows X:\Y\Z
-      @class_name = 1
+      @class_name_idx = 1
       @path_delim = '\\'
     else
       # Unix Based /X/Y/Z
-      @class_name = 0
+      @class_name_idx = 0
       @path_delim = '/'
     end
   end
@@ -158,9 +223,9 @@ class ParseOutput
 
     puts 'Parsing file: ' + file_name
 
-    test_pass = 0
-    test_fail = 0
-    test_ignore = 0
+    @test_passed = 0
+    @test_failed = 0
+    @test_ignored = 0
     puts ''
     puts '=================== RESULTS ====================='
     puts ''
@@ -175,43 +240,52 @@ class ParseOutput
       line_array = line.split(':')
 
       # 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.
-      if (line_array.size >= 4) || (line.start_with? 'TEST(')
-        # Determine if this test passed
-        if line.include? ':PASS'
+      # were found. Case is important.
+      if (line_array.size >= 4) || (line.start_with? 'TEST(') || (line.start_with? 'IGNORE_TEST(')
+
+        # check if the output is fixture output (with verbose flag "-v")
+        if (line.start_with? 'TEST(') || (line.start_with? 'IGNORE_TEST(')
+          line_array = prepare_fixture_line(line)
+          if line.include? ' PASS'
+            test_passed_unity_fixture(line_array)
+            @test_passed += 1
+          elsif line.include? 'FAIL'
+            test_failed_unity_fixture(line_array)
+            @test_failed += 1
+          elsif line.include? 'IGNORE'
+            test_ignored_unity_fixture(line_array)
+            @test_ignored += 1
+          end
+        # normal output / fixture output (without verbose "-v")
+        elsif line.include? ':PASS'
           test_passed(line_array)
-          test_pass += 1
+          @test_passed += 1
         elsif line.include? ':FAIL'
           test_failed(line_array)
-          test_fail += 1
+          @test_failed += 1
         elsif line.include? ':IGNORE:'
           test_ignored(line_array)
-          test_ignore += 1
+          @test_ignored += 1
         elsif line.include? ':IGNORE'
           line_array.push('No reason given')
           test_ignored(line_array)
-          test_ignore += 1
-        elsif line.start_with? 'TEST('
-          if line.include? ' PASS'
-            line_array = line.split(' ')
-            test_passed_unity_fixture(line_array)
-            test_pass += 1
-          end
+          @test_ignored += 1
         end
+        @total_tests = @test_passed + @test_failed + @test_ignored
       end
     end
     puts ''
     puts '=================== SUMMARY ====================='
     puts ''
-    puts 'Tests Passed  : ' + test_pass.to_s
-    puts 'Tests Failed  : ' + test_fail.to_s
-    puts 'Tests Ignored : ' + test_ignore.to_s
-    @total_tests = test_pass + test_fail + test_ignore
+    puts 'Tests Passed  : ' + @test_passed.to_s
+    puts 'Tests Failed  : ' + @test_failed.to_s
+    puts 'Tests Ignored : ' + @test_ignored.to_s
 
     return unless @xml_out
 
-    heading = '<testsuite name="Unity" tests="' + @total_tests.to_s + '" failures="' + test_fail.to_s + '"' + ' skips="' + test_ignore.to_s + '">'
-    @array_list.insert(0, heading)
+    # push information about the suite
+    push_xml_output_suite_info
+    # write xml output file
     write_xml_output
   end
 end

From 38e1ee872ccf2989ff873415ce98fd20ba9c2f1a Mon Sep 17 00:00:00 2001
From: Fabian Zahn <fabian.zahn@gmail.com>
Date: Tue, 27 Feb 2018 07:23:18 +0100
Subject: [PATCH 5/5] Added some useful documentation which states the output
 formats that are parseable by this script.

---
 auto/parse_output.rb | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/auto/parse_output.rb b/auto/parse_output.rb
index cbafd7c..f04508f 100644
--- a/auto/parse_output.rb
+++ b/auto/parse_output.rb
@@ -10,6 +10,11 @@
 #    To capture an output file under Linux builds use the following:
 #      make | tee Output.txt
 #
+#    This script can handle the following output formats:
+#    - normal output (raw unity)
+#    - fixture output (unity_fixture.h/.c)
+#    - fixture output with verbose flag set ("-v")
+#
 #    To use this parser use the following command
 #    ruby parseOutput.rb [options] [file]
 #        options: -xml  : produce a JUnit compatible XML file
@@ -230,12 +235,25 @@ class ParseOutput
     puts '=================== RESULTS ====================='
     puts ''
     File.open(file_name).each do |line|
-      # Typical test lines look like this:
+      # Typical test lines look like these:
+      # ----------------------------------------------------
+      # 1. normal output:
       # <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)
+      # 2. fixture output
+      # <path>/<test_file>.c:63:TEST(<test_group>, <test_function>):FAIL: Expected 0x00001234 Was 0x00005A5A
+      # <path>/<test_file>.c:36:TEST(<test_group>, <test_function>):IGNORE
+      # Note: "PASS" information won't be generated in this mode
+      #
+      # 3. fixture output with verbose information ("-v")
+      # TEST(<test_group, <test_file>)<path>/<test_file>:168::FAIL: Expected 0x8D Was 0x8C
+      # TEST(<test_group>, <test_file>)<path>/<test_file>:22::IGNORE: This Test Was Ignored On Purpose
+      # IGNORE_TEST(<test_group, <test_file>)
+      # TEST(<test_group, <test_file>) PASS
+      #
+      # Note: Where path is different on Unix vs Windows devices (Windows leads with a drive letter)!
       set_os_specifics(line)
       line_array = line.split(':')