Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Re: Using guards for script execution?

by Marshall (Canon)
on Mar 01, 2017 at 05:05 UTC ( [id://1183241]=note: print w/replies, xml ) Need Help??


in reply to Using guards for script execution?

A few comments to your Perl code,
sub main { print "Hello, world!\n"; } unless (caller) { main; }
This code is a weird formulation because the file that contains main() will always be executed as a main program? Normal practice would be to do away with this extra level of indentation implied by the subroutine main and just start writing the "main" code. The unless (caller){} does nothing useful. You could have just put a simple main(); instead to call the sub main.

I attach demomain.pl and demo.pm below.
Note that demomain.pl could have been called "demo.pl", but I didn't want to confuse you. Anyway note that you can have a .pm file of the same name as a .pl file.

In my demo.pm file, I use caller(), test() if !caller;. If demo.pm is being run as a main program, test() will execute. If demo.pm is being "used" by another program, say by demomain.pl, all of the top-level code in demo.pm will run, but test() will not run because Perl knows that demo.pm is not being run as a main program. There is no need to so something similar in your main.pl program because your main is always a main program!

This provides a very "lightweight" test framework. There are such things as .t files which are used in more complicated situations.

It is possible to split a main program across multiple files, i.e., same package in multiple files. I don't demo that because I think it is a very bad idea.

#!/usr/bin/perl # File: demo.pl use strict; use warnings; $|=1; # turn off buffering use Demo qw(example); # test() is not exported by Demo.pl # this the error produced... # Undefined subroutine &main::test called at C:\Projects_Perl\testing\ +demo.pl line 7. # my $x = test(); my $y = Demo::test(); #this is ok , Fully qualified name print "test() returned $y\n"; __END__ Prints: top level in Demo.pm this is the test subroutine! test() returned 1
#!/usr/bin/perl # File: Demo.pm use strict; use warnings; package Demo; use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION); use Exporter; our $VERSION=1.01; our @ISA = qw(Exporter); our @EXPORT = qw(); our @EXPORT_OK = qw(example); our $DEBUG =0; test() if !caller; # runs test() if run as a "main program" sub test { print "this is the test subroutine!\n"; return 1;} sub example {return "this is an example"}; print "top level in Demo.pm\n"; 1;

Replies are listed 'Best First'.
Re^2: Using guards for script execution? (testing)
by tye (Sage) on Mar 01, 2017 at 16:18 UTC

    Actually, there can be value to writing a script like:

    #!/usr/bin/perl -w use strict; use Some::Module qw< this that >; my $Config = ...; Main( @ARGV ) if $0 eq __FILE__; return 0; # Exits -- no run-time code below this point, just 'sub's. sub Main { ... }

    Because it allows you to write more types of tests for the code included in the script. An automated test can require or do the script in order to have the global configuration initialized (which should not involve any interesting calculations) and then the test can do some setup and then call subroutines (including Main) from the script. An automated test can even do some setup, set C<$0>, then require/do the script and it will execute normally (except for things set up by the test) and then return control to the test where aspects of the process can be checked.

    Yes, you can also do even more work to move absolutely all of the code out of the script and into one or more modules and then do all of those types of tests using the module(s). Indeed, there can be even more benefits to moving all of the code to modules. But my experience is that very often this extra work is not warranted for at least some of the code in a script and the trivial work of allowing the script itself to be loaded without it always running is all that is needed to make complete automated testing possible.

    - tye        

      That is far too 20th century for my tastes. You should not test scripts, you should test interfaces. Your scripts really should just be stubs that call one method: run()

        “My tastes?” There is no “my” in anonymity. Whatever you are is devoid of tastes; taste.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1183241]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (7)
As of 2024-04-19 07:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found