in reply to Re: BEGIN and END blocks, use strict and scoping
in thread BEGIN and END blocks, use strict and scoping

If I understand you correctly, the END block can make use of lexical variables defined in the file before the END block itself. This would obviate the need for using a BEGIN block to test for the presence/absence on disk of a given file. It would also mean that I could place use strict; in its customary position.

The following little script should illustrate the point in various ways depending on whether the file present is indeed present and depending on whether the croak call is live or commented-out.

#!/usr/local/bin/perl use strict; use warnings; use File::Copy; use Carp; use Test::More (qw|no_plan|); my $test = "/Users/jimk/present"; my $hide = $test . '.hidden'; my $status; if (-f $test) { $status = 1; move($test, $hide); ok(! -f $test, "original file no longer present"); ok( -f $hide, "hidden file present"); } else { open FH, ">$test"; print FH "1\n"; close FH; ok(-f $test, "file created where it didn't previously exist"); ok(1, "test not relevant"); } my $trick = 0; if (! $trick) { croak "Trick is false"; } END { if ($status) { move($hide, $test); ok(! -f $hide, "hidden file no longer present"); ok( -f $test, "original file once again present"); } else { unlink $test; ok(! -f $test, "specially created file has been removed"); ok(1, "test not relevant"); } }

Update: While the solution above guarantees that the testing process is (more) non-destructive, it does have one drawback, AFACIT. When the croak occurs earlier in the file, (1) the total number of tests run is reduced by the quantity lying between the croak and the END block and (2) the numbers associated with the tests inside the END block are no longer at the end of the range predicted by the plan.

Revised example:

#!/usr/local/bin/perl use strict; use warnings; use File::Copy; use Carp; use Test::More tests => 7; # (qw|no_plan|); my $test = "/Users/jimk/present"; my $hide = $test . '.hidden'; my $status; my $trick = 0; if (-f $test) { $status = 1; move($test, $hide); ok(! -f $test, "original file no longer present"); ok( -f $hide, "hidden file present"); } else { open FH, ">$test"; print FH "1\n"; close FH; ok(-f $test, "file created where it didn't previously exist"); ok(1, "test not relevant"); } croak "Trick is false" unless $trick; ok('alpha', "alpha reached"); ok('beta', "beta reached"); ok('gamma', "gamma reached"); # croak "Trick is false" unless $trick; END { if ($status) { move($hide, $test); ok(! -f $hide, "hidden file no longer present"); ok( -f $test, "original file once again present"); } else { unlink $test; ok(! -f $test, "specially created file has been removed"); ok(1, "test not relevant"); } }

... produces (assuming that present was indeed present at the outset):

1..7 ok 1 - original file no longer present ok 2 - hidden file present Trick is false at end.pl line 28 ok 3 - hidden file no longer present ok 4 - original file once again present # Looks like you planned 7 tests but only ran 4. # Looks like your test died just after 4.
Tests 3 and 4 above are not the third and fourth as you would intuitively predict from eyeballing the file. You become more dependent on the croak message in locating the error within the file.

Thanks!

Jim Keenan

Replies are listed 'Best First'.
Re^3: BEGIN and END blocks, use strict and scoping
by dragonchild (Archbishop) on Sep 25, 2005 at 02:51 UTC
    Now, you move from having an issue with understanding how use and BEGIN work to an issue with how Test::More works. Modify your code as such:
    unless ( $trick ) { SKIP: { skip 3, "About to croak!\n"; } croak; } else { # Do your three other tests here. }
    You just have to let Test::More know what's going on with regards to your test plan. It's called a plan for a reason.

    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?