Author: dagolden
Date: Sun Aug 30 18:26:43 2009
New Revision: 13237

Modified:
   Module-Build/trunk/Changes
   Module-Build/trunk/lib/Module/Build/Base.pm
   Module-Build/trunk/t/lib/DistGen.pm
   Module-Build/trunk/t/use_tap_harness.t

Log:
die on test failure when using TAP::Harness

Test::Harness dies on failure but TAP::Harness does not.  We now
emulate this behavior of Test::Harness when running tests with
TAP::Harness.  The change happens in do_tests() so that subclasses
may call run_tap_harness() and get back the TAP::Parser::Aggregator
object directly for more sophisticated testing and analysis.

I also added tests for this new behavior and did some minor cleanup
of t/use_tap_harness.t along the way.



Modified: Module-Build/trunk/Changes
==============================================================================
--- Module-Build/trunk/Changes  (original)
+++ Module-Build/trunk/Changes  Sun Aug 30 18:26:43 2009
@@ -14,6 +14,9 @@
  - Fix the t/destinations.t fix. [David Golden, with thanks to Eric Wilhelm]
  - Fix recursive test files in generated Makefile.PL (RT#49254) [Sawyer X]
  - Guard against trying :utf8 when :utf8 isn't available
+ - The "test" action now dies when using the 'use_tap_harness'
+   option and tests fail, matching the behavior under Test::Harness. 
+   (RT#49080) [initial patch from David Wheeler; revised by David Golden]
 
 0.35 - Thu Aug 27 09:12:02 EDT 2009
 

Modified: Module-Build/trunk/lib/Module/Build/Base.pm
==============================================================================
--- Module-Build/trunk/lib/Module/Build/Base.pm (original)
+++ Module-Build/trunk/lib/Module/Build/Base.pm Sun Aug 30 18:26:43 2009
@@ -2276,6 +2276,8 @@
   $self->do_tests;
 }
 
+# Test::Harness dies on failure but TAP::Harness does not, so we must
+# die if running under TAP::Harness
 sub do_tests {
   my $self = shift;
 
@@ -2284,7 +2286,8 @@
   if(@$tests) {
     my $args = $self->tap_harness_args;
     if($self->use_tap_harness or ($args and %$args)) {
-      $self->run_tap_harness($tests);
+      my $aggregate = $self->run_tap_harness($tests);
+      $self->_tap_harness_exit($aggregate) if $aggregate->has_errors;
     }
     else {
       $self->run_test_harness($tests);
@@ -2304,12 +2307,36 @@
 
   # TODO allow the test @INC to be set via our API?
 
-  TAP::Harness->new({
+  my $aggregate = TAP::Harness->new({
     lib => [...@inc],
     verbosity => $self->{properties}{verbose},
     switches  => [ $self->harness_switches ],
     %{ $self->tap_harness_args },
   })->runtests(@$tests);
+
+  return $aggregate;
+}
+
+# Emulate death on failure behavior of Test::Harness
+sub _tap_harness_exit {
+  my ($self, $aggregate) = @_;
+
+  my $total  = $aggregate->total;
+  my $passed = $aggregate->passed;
+  my $failed = $aggregate->failed;
+
+  my @parsers = $aggregate->parsers;
+
+  my $num_bad = 0;
+  for my $parser (@parsers) {
+    $num_bad++ if $parser->has_problems;
+  }
+
+  die(sprintf(
+      "Failed %d/%d test programs. %d/%d subtests failed.\n",
+      $num_bad, scalar @parsers, $failed, $total
+    )
+  ) if $num_bad;
 }
 
 sub run_test_harness {

Modified: Module-Build/trunk/t/lib/DistGen.pm
==============================================================================
--- Module-Build/trunk/t/lib/DistGen.pm (original)
+++ Module-Build/trunk/t/lib/DistGen.pm Sun Aug 30 18:26:43 2009
@@ -428,7 +428,9 @@
 }
 
 sub change_build_pl {
-  my ($self, $opts) = @_;
+  my ($self, @opts) = @_;
+
+  my $opts = ref $opts[0] eq 'HASH' ? $opts[0] : { @opts };
 
   local $Data::Dumper::Terse = 1;
   (my $args = Dumper($opts)) =~ s/^\s*\{|\}\s*$//g;

Modified: Module-Build/trunk/t/use_tap_harness.t
==============================================================================
--- Module-Build/trunk/t/use_tap_harness.t      (original)
+++ Module-Build/trunk/t/use_tap_harness.t      Sun Aug 30 18:26:43 2009
@@ -4,7 +4,7 @@
 use Test::More;
 use lib $ENV{PERL_CORE} ? '../lib/Module/Build/t/lib' : 't/lib';
 if (eval { require TAP::Harness } && TAP::Harness->VERSION >= 3) {
-    plan tests => 8;
+    plan tests => 11;
 } else {
     plan skip_all => 'TAP::Harness 3+ not installed'
 }
@@ -17,16 +17,20 @@
 my $tmp = MBTest->tmpdir;
 my $dist = DistGen->new( dir => $tmp );
 $dist->regen;
-
 $dist->chdir_in;
+
 #########################
 
 # Make sure that TAP::Harness properly does its thing.
-ok my $mb = Module::Build->new(
+$dist->change_build_pl(
     module_name     => $dist->name,
     use_tap_harness => 1,
     quiet           => 1,
-), 'Construct build object with test_file_exts parameter';
+);
+$dist->regen;
+
+ok my $mb = $dist->new_from_context, 
+    'Construct build object with test_file_exts parameter';
 
 $mb->add_to_cleanup('save_out');
 # Use uc() so we don't confuse the current test output
@@ -40,12 +44,16 @@
 #########################
 
 # Make sure that arguments are passed through to TAP::Harness.
-ok $mb = Module::Build->new(
+$dist->change_build_pl(
     module_name     => $dist->name,
     use_tap_harness => 1,
     tap_harness_args => { verbosity => 0 },
     quiet           => 1,
-), 'Construct build object with test_file_exts parameter';
+);
+$dist->regen;
+
+ok $mb = $dist->new_from_context, 
+    'Construct build object with test_file_exts parameter';
 
 $mb->add_to_cleanup('save_out');
 # Use uc() so we don't confuse the current test output
@@ -56,6 +64,35 @@
 unlike $out, qr/^OK 1/m, 'Should not see first test output';
 like $out, qr/^ALL TESTS SUCCESSFUL/m, 'Should see test success message';
 
+#--------------------------------------------------------------------------#
+# test that a failing test dies
+#--------------------------------------------------------------------------#
+
+$dist->change_build_pl(
+    module_name     => $dist->name,
+    use_tap_harness => 1,
+    tap_harness_args => { verbosity => 1 },
+    quiet           => 1,
+);
+$dist->change_file('t/basic.t',<<"---");
+use Test::More tests => 1;
+use strict;
+
+use $dist->{name};
+ok 0;
+---
+$dist->regen;
+
+ok $mb = $dist->new_from_context, 
+    'Construct build object after setting tests to fail'; 
+# Use uc() so we don't confuse the current test output
+my $out = stdout_stderr_of( sub { $dist->run_build('test')} );
+ok( $?, "'Build test' had non-zero exit code" );
+like( $out, qr{Failed 1/1 test programs. 1/1 subtests failed\.}, 
+    "Saw emulated Test::Harness die() message" 
+);
+
+
 $dist->remove;
 
 # vim:ts=4:sw=4:et:sta

Reply via email to