You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by jm...@apache.org on 2008/03/27 16:48:07 UTC

svn commit: r641857 - in /spamassassin/trunk/build/hudson: run_build tap-to-junit-xml

Author: jm
Date: Thu Mar 27 08:48:06 2008
New Revision: 641857

URL: http://svn.apache.org/viewvc?rev=641857&view=rev
Log:
major fixes to the TAP-to-JUnit-XML conversion tool; Hudson test report should be much improved

Modified:
    spamassassin/trunk/build/hudson/run_build
    spamassassin/trunk/build/hudson/tap-to-junit-xml

Modified: spamassassin/trunk/build/hudson/run_build
URL: http://svn.apache.org/viewvc/spamassassin/trunk/build/hudson/run_build?rev=641857&r1=641856&r2=641857&view=diff
==============================================================================
--- spamassassin/trunk/build/hudson/run_build (original)
+++ spamassassin/trunk/build/hudson/run_build Thu Mar 27 08:48:06 2008
@@ -3,7 +3,7 @@
 . /export/home/jm/tools/setenvs
 
 # clean everything first
-rm -rf t/log t/log.* artifacts testxml || true
+rm -rf t/log t/log.* artifacts testxml Mail-SpamAssassin* || true
 make distclean < /dev/null || true
 mkdir artifacts testxml
 
@@ -17,8 +17,12 @@
 mv t/log artifacts/t.log.make_test
 
 # generate 't/log.make_disttest'
-make disttest TEST_VERBOSE=1 < /dev/null \
-    2>&1 | tee artifacts/make_disttest.log
+(
+  # this hack is required to produce verbose disttest output
+  PASTHRU='TEST_VERBOSE=1'; export PASTHRU          
+  make -e disttest TEST_VERBOSE=1 < /dev/null \
+      2>&1 | tee artifacts/make_disttest.log
+)
 mv Mail-SpamAssassin*/t/log artifacts/t.log.make_disttest
 
 # and 't/log.make_test_p561'
@@ -30,18 +34,19 @@
 mv t/log artifacts/t.log.make_test_p561
 
 # generate XML test reports (multifile)
-# perl ./build/hudson/tap-to-junit-xml \
-    # "make test" testxml/make_test < artifacts/make_test.log
-# perl ./build/hudson/tap-to-junit-xml \
-    # "make disttest" testxml/make_disttest < artifacts/make_disttest.log
-# perl ./build/hudson/tap-to-junit-xml \
-    # "make test p561" testxml/make_test_p561 < artifacts/make_test_p561.log
-
-# generate XML test reports (single file)
 perl ./build/hudson/tap-to-junit-xml \
-    "make test" < artifacts/make_test.log > testxml/make_test.xml
+    "make test" testxml/make_test < artifacts/make_test.log
 perl ./build/hudson/tap-to-junit-xml \
-    "make disttest" < artifacts/make_disttest.log > testxml/make_disttest.xml
+    "make disttest" testxml/make_disttest < artifacts/make_disttest.log
 perl ./build/hudson/tap-to-junit-xml \
-    "make test p561" < artifacts/make_test_p561.log > testxml/make_test_p561.xml
+    "make test with perl561" testxml/make_test_p561 < artifacts/make_test_p561.log
+
+# generate XML test reports (single file, runs into Hudson bug where it
+# cannot read <system-out> correctly)
+# perl ./build/hudson/tap-to-junit-xml \
+    # "make test" < artifacts/make_test.log > testxml/make_test.xml
+# perl ./build/hudson/tap-to-junit-xml \
+    # "make disttest" < artifacts/make_disttest.log > testxml/make_disttest.xml
+# perl ./build/hudson/tap-to-junit-xml \
+    # "make test p561" < artifacts/make_test_p561.log > testxml/make_test_p561.xml
 

Modified: spamassassin/trunk/build/hudson/tap-to-junit-xml
URL: http://svn.apache.org/viewvc/spamassassin/trunk/build/hudson/tap-to-junit-xml?rev=641857&r1=641856&r2=641857&view=diff
==============================================================================
--- spamassassin/trunk/build/hudson/tap-to-junit-xml (original)
+++ spamassassin/trunk/build/hudson/tap-to-junit-xml Thu Mar 27 08:48:06 2008
@@ -11,7 +11,8 @@
 
 Parse test suite output in TAP (Test Anything Protocol,
 C<http://testanything.org/>) format, and produce XML output in a similar format
-to that produced by the <junit> ant task.
+to that produced by the <junit> ant task.  This is useful for consumption by
+continuous-integration systems like Hudson (C<https://hudson.dev.java.net/>).
 
 C<"test suite name"> is a descriptive string used as the B<name> attribute on the
 top-level <testsuites> node of the output XML.
@@ -33,6 +34,7 @@
 
 =head1 BUGS
 
+  - Output is optimized for Hudson, and may not look quite as good in other UIs.
   - Doesn't do anything with the STDERR from tests.
   - Doesn't fill in the 'errors' attribute in the  <testsuite> element.
   - Doesn't handle "todo" or "skip"
@@ -45,6 +47,10 @@
 
 pretty much entirely rewritten by Justin Mason <junit at jmason.org>, Feb 2008.
 
+=head1 VERSION
+
+Mar 27 2008 jm 
+
 =head1 COPYRIGHT & LICENSE
 
 Copyright (c) 2007 Matisse Enzer. All Rights Reserved.
@@ -69,7 +75,12 @@
 use Time::HiRes qw(gettimeofday tv_interval);
 use XML::Generator qw(:noimport);
 
+# should the 'Test Summary Report' at the end of a test suite be displayed
+# as if it was a testcase?  in my opinion, no
+my $HIDE_TEST_SUMMARY_REPORT = 1;
+
 my $suite_name = $opt_suitename || 'make test';
+my $safe_suite_name = $suite_name; $safe_suite_name =~ s/[^-:_A-Za-z0-9]+/_/gs;
 
 # TODO: it'd be nice to respect 'Universal desirable behavior #1' from
 # http://testanything.org/wiki/index.php/TAP_Consumers -- 'Should work on the
@@ -80,6 +91,7 @@
 
 my $tap     = TAP::Parser->new( { tap => $tout } );
 my $xmlgen = XML::Generator->new( ':pretty', ':std');
+my $xmlgenunescaped = XML::Generator->new( ':pretty', ':std', 'escape' => 'unescaped');
 my @properties = _get_properties($xmlgen);
 my $test_results = _parse_tests( $tap, $xmlgen );
 
@@ -97,7 +109,7 @@
   my $xml = "<?xml version='1.0' encoding='UTF-8' ?>\n" . 
           $xmlgen->testsuites({
               name => $suite_name,
-            }, @$test_results );
+            }, @$test_results);
   return $xml;
 }
 
@@ -119,7 +131,7 @@
 
   my $ctx = {
     testsuites => [ ],
-    test_name => 'unknown',
+    test_name => 'notest',
     plan_ntests => 0,
     case_id => 0,
   };
@@ -193,15 +205,30 @@
         $ctx->{case_tests}++;
         $ctx->{case_failures}++;
         my $test_case = {
-            classname => $ctx->{test_name},
-            name      => $ctx->{test_name},
+            classname => test_name_to_classname($ctx->{test_name}),
+            name      => 'result',
             'time'    => 0,
         };
         my $failure = $xmlgen->failure({
           type => "OverallTestsFailed",
           message => $s
-        }, $s);
-        push @{$ctx->{test_cases}}, $xmlgen->testcase($test_case, $failure);
+        }, "__FAILUREMESSAGETODO__");
+
+        if (!$HIDE_TEST_SUMMARY_REPORT) {
+          push @{$ctx->{test_cases}}, $xmlgen->testcase($test_case, $failure);
+        }
+      }
+      elsif ($s =~ /^(\S+?)\.\.\.+1\.\.(\d+?)\s*$/) {
+        # perl 5.6.x "Test" format plan line
+        # unknown t/basic_lint....................1..1
+
+        my ($name, $nt) = ($1,$2);
+        if ($ctx->{plan_ntests}) {       # only if there have been tests planned
+          _finish_test_block($ctx);
+        }
+
+        $ctx->{plan_ntests} = $nt+0;
+        $ctx->{test_name} = "$name.t";
       }
     }
     elsif ($t eq 'plan') {
@@ -227,9 +254,12 @@
         next;
       }
 
+      # clean this up in a Hudson-compatible way; ":" and "/" are out, "." also causes
+      # trouble by creating an extra "directory" in the results
+
       my $test_case = {
-          classname => $ctx->{test_name},
-          name      => "$ctx->{test_name}: $ntest",
+          classname => test_name_to_classname($ctx->{test_name}),
+          name      => sprintf("test %6d", $ntest), # space-padding ensures ordering
           'time'    => 0,
       };
 
@@ -240,14 +270,30 @@
         $failure = $xmlgen->failure({
           type => "TAPTestFailed",
           message => $s
-        }, $s);
+        }, "__FAILUREMESSAGETODO__");
+        push @{$ctx->{test_cases}}, $xmlgen->testcase($test_case, $failure);
+      }
+      else {
+        push @{$ctx->{test_cases}}, $xmlgen->testcase($test_case);
       }
-      push @{$ctx->{test_cases}}, $xmlgen->testcase($test_case, $failure);
     }
       
     $ctx->{sysout} .= $s."\n";
   }
 
+  if (scalar(@{$ctx->{test_cases}}) == 0 &&
+      scalar(@{$ctx->{testsuites}}) == 0)
+  { 
+    # no tests found! create a <testsuite> block containing *something* at least
+    $ctx->{case_tests}++;
+    my $test_case = {
+        classname => test_name_to_classname($ctx->{test_name}),
+        name      => 'result',
+        'time'    => 0,
+    };
+    push @{$ctx->{test_cases}}, $xmlgen->testcase($test_case);
+  }
+
   _finish_test_block($ctx);
   return $ctx->{testsuites};
 }
@@ -273,29 +319,44 @@
 
   # clean it up to valid Java packagename format (or at least something Hudson will
   # consume)
-  my $name = $suite_name.":".$ctx->{test_name};
+  my $name = $ctx->{test_name};
   $name =~ s/[^-:_A-Za-z0-9]+/_/gs;
+  $name = "$safe_suite_name.$name";      # a "directory" for the suite name
 
   my $testsuite = {
       'time'         => $elapsed_time,
       'name'         => $name,
-      'package'      => $name,
       tests          => $ctx->{case_tests},
       failures       => $ctx->{case_failures},
       'id'           => $ctx->{case_id},
       errors         => 0,
   };
-  my $system_out = 'system-out';
-  my $system_err = 'system-err';
 
-  push @{$ctx->{testsuites}}, $xmlgen->testsuite($testsuite,
-          @{$ctx->{test_cases}},
-          $xmlgen->$system_out($ctx->{sysout}),
-          $xmlgen->$system_err());
+  my @fixedcases = ();
+  foreach my $tc (@{$ctx->{test_cases}}) {
+    if ($tc =~ s/__FAILUREMESSAGETODO__/ cdata($ctx->{sysout}) /ges) {
+      push @fixedcases, \$tc;       # inhibits escaping!
+    } else {
+      push @fixedcases, $tc;
+    }
+  }
+
+  # use "unescaped"; we have already fixed escaping on these strings.
+  # note that a reference means 'this is unescaped', bizarrely.
+  push @{$ctx->{testsuites}}, $xmlgenunescaped->testsuite($testsuite,
+          @fixedcases,
+          \("<system-out>\n".cdata($ctx->{sysout})."\n</system-out>"),
+          \("<system-err />"));
 
   _new_ctx($ctx);
 };
 
+sub cdata {
+  my $s = shift;
+  $s =~ s/\]\]>/\](warning: defanged by tap-to-junit-xml)\]>/gs;
+  return '<![CDATA['.$s.']]>';
+}
+
 sub _get_properties {
     my $xmlgen = shift;
     my @props;
@@ -305,7 +366,20 @@
     return @props;
 }
 
+sub test_name_to_classname {
+  my $safe = shift;
+  $safe =~ s/[^-:_A-Za-z0-9]+/_/gs;
+  $safe = "$safe_suite_name.$safe";      # a "directory" for the suite name
+  $safe;
+}
+
 __END__
 
 # JUnit references:
-# see http://www.nabble.com/JUnit-4-XML-schematized--td13946472.html
+# http://www.nabble.com/JUnit-4-XML-schematized--td13946472.html
+# http://jra1mw.cvs.cern.ch:8180/cgi-bin/jra1mw.cgi/org.glite.testing.unit/config/JUnitXSchema.xsd?view=markup
+# skipped tests:
+# https://hudson.dev.java.net/issues/show_bug.cgi?id=1251
+# Hudson source:
+# http://fisheye5.cenqua.com/browse/hudson/hudson/main/core/src/main/java/hudson/tasks/junit/CaseResult.java
+