develooper Front page | perl.perl5.porters | Postings from February 2003

Re: [perl #18810] C<use Test::More;> causes C<BEGIN> blocks to be skipped.

Thread Previous | Thread Next
From:
sthoenna
Date:
February 10, 2003 18:58
Subject:
Re: [perl #18810] C<use Test::More;> causes C<BEGIN> blocks to be skipped.
Message ID:
4lgR+gzkgKMI092yn@efn.org
On 2 Dec 2002 10:31:49 -0000, abigail@foad.org wrote:
>    #!/usr/bin/perl
>
>    use strict;
>    use warnings;
>
>    use Test::More tests => 1;
>
>    BEGIN {
>        use_ok "Carp";
>        print "BEGIN run\n";
>    }
>    __END__
>
>This will give the expected:
>
>    1..1
>    ok 1 - use Carp;
>    BEGIN run
>
>
>But if omit the 'test => 1' arguments to the 'use Test::More' statement,
>no output at all is generated - the BEGIN block isn't run. 

20823
Finally tracked this down to bizzare behaviour from:

~ $perl -wle'BEGIN {local $@; die "foo"; print "bar"} print "baz"'
baz

The "gotta have a plan" croak in Test::Builder::ok is not working; it
just terminates execution of the begin block.  (A local($@) is done in
use_ok() just before doing the eval "use..."  and calling ok.)  I've
opened a separate ticket: [perl #20823] to track the actual perl bug.

Here's a workaround for Test::More 0.48_01.  require_ok and isa_ok are
also potentially subject to the bug, but I wouldn't expect them to be
called in a BEGIN block.

While poking around, I also noticed Test::More refers to
$Test::Builder::No_Plan in a couple places, but there is no such
variable.  (Test::Builder has a lexical $No_Plan.)  I was going to
change the "unless $Test::Builder::No_Plan" to
"if $Test->expected_tests", but the Test::More code made no sense
to me.  If skip() and todo_skip() can default to skipping one test
in the no_plan case, why not when there is a plan?  If it is changed
to call expected_tests, Test::Builder::no_plan() should zero out
$Expected_Tests.  Likewise, Test::Builder::expected_tests should
clear $No_Plan.

--- lib/Test/More.pm.orig	Sun Nov 10 23:36:16 2002
+++ lib/Test/More.pm	Mon Feb 10 18:13:52 2003
@@ -694,6 +694,14 @@ because the notion of "compile-time" is 
   BEGIN { use_ok('Some::Module') }
   BEGIN { ...some code that depends on the use... }
 
+Also, don't try to do this:
+
+  use Test::More;
+  plan tests => _count_my_tests();
+  BEGIN { use_ok('Some::Module') }
+
+since the plan will not have been set at the time use_ok is called.
+
 
 =cut
 
@@ -703,32 +711,39 @@ sub use_ok ($;@) {
 
     my($pack,$filename,$line) = caller;
 
-    local($@,$!);   # eval sometimes interferes with $!
+    my $errmsg;
 
-    if( @imports == 1 and $imports[0] =~ /^\d+(?:\.\d+)?$/ ) {
-        # probably a version check.  Perl needs to see the bare number
-        # for it to work with non-Exporter based modules.
-        eval <<USE;
+    # extra block around the local($@) to work around a perl bug
+    # [perl #20832] with die ($Test->ok croaking when there is no plan)
+    {
+	local($@,$!);   # eval sometimes interferes with $!
+
+	if( @imports == 1 and $imports[0] =~ /^\d+(?:\.\d+)?$/ ) {
+	    # probably a version check.  Perl needs to see the bare number
+	    # for it to work with non-Exporter based modules.
+	    eval <<USE;
 package $pack;
 use $module $imports[0];
 USE
-    }
-    else {
-        eval <<USE;
+	}
+	else {
+	    eval <<USE;
 package $pack;
 use $module \@imports;
 USE
+	}
+	$errmsg = $@;
     }
 
-    my $ok = $Test->ok( !$@, "use $module;" );
+    my $ok = $Test->ok( !$errmsg, "use $module;" );
 
     unless( $ok ) {
-        chomp $@;
-        $@ =~ s{^BEGIN failed--compilation aborted at .*$}
+        chomp $errmsg;
+        $errmsg =~ s{^BEGIN failed--compilation aborted at .*$}
                 {BEGIN failed--compilation aborted at $filename line $line.}m;
         $Test->diag(<<DIAGNOSTIC);
     Tried to use '$module'.
-    Error:  $@
+    Error:  $errmsg
 DIAGNOSTIC
 
     }
End of Patch.

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About