How can I test a standalone Perl script?

前端 未结 7 1407
太阳男子
太阳男子 2021-02-01 05:07

I have written a small Perl script and now I would like to create a test suite for it. I thought it would be nice to be able to use the script as a module, import t

相关标签:
7条回答
  • 2021-02-01 05:31

    Since brian seems to be asleep right now, here's a pointer to what he calls modulinos. This is basically a recipe for building scripts that act like modules or modules that can be run like scripts. Sounds exactly like what you are looking for.

    Mastering Perl is definitely a book worth reading (and buying).

    0 讨论(0)
  • 2021-02-01 05:34

    Since I just wanted to test one sub, I used the hacky solution of extracting that sub into a module with a perl one-liner, which is easy to understand and doesn't require to install any modules (I extract the paragraph with the sub name which is of course brittle). So in my Makefile I have:

    MyModule.pm: my_script.pl
        perl -00 -lnE 'if(/^\s*sub my_sub \{/){say "package MyModule;";say;say "1;";}' my_script.pl >|MyModule.pm
    
    0 讨论(0)
  • 2021-02-01 05:34

    While making some CGI style perl scripts remotely testable (without looping thru CGI-test modules) I ended up doing something like this:

    bin/myscript.pl:

    use …;
    
    do {
      return 1 if $ENV{INCLUDED_AS_MODULE};
    
      … original script without the subs …
    };
    
    sub some_sub {
     …
    }
    sub …
    sub …
    

    t/mytest.t:

    use Test::More;
    use FindBin qw/$Bin/;
    
    BEGIN {
      $ENV{INCLUDED_AS_MODULE} = 1;
      my $filename = "$Bin/../bin/myscript.pl";
      do $filename or die "Unable to open '$filename': $! ($@)";
    }
    
    ok some_sub(), 'some sub returns true';
    …
    done_testing;
    

    This imports the subs into the main namespace of the test and can be tested easily.

    EDIT: And after some more searching for what I was looking for, I realize modulinos are basically what I did, but avoiding communicating via ENV, putting all your code in a method and just checking wether there is a caller():

    https://www.perlmonks.org/bare/?node_id=537377 (link in a previous answer did not seem to work)

    0 讨论(0)
  • 2021-02-01 05:41

    I want to do the same thing. Is there a reason not to do the following? (I'm not a perl expert, the solution seems to work fine for me, though.):

    in the beginning of the script I ask for a switch ("-test") or whatever and than branch to a sub like this:

    my $myargs = CmdLineOptions->new( args=>\@ARGV );
    if ($myargs->was_given(option=>"-test"))    { &tests; }
    
    sub tests   {
        require "Test/More.pm";
        Test::More->import('no_plan');
    
        is(1,1,"my tests go here");
        exit;
    }
    

    (by using require and import i suppress the '# No tests run!' message i get when using the 'use Test::More' without doing any tests. I guess it also reduces the overhead.)

    0 讨论(0)
  • 2021-02-01 05:45

    It depends on whether you want to test the script itself, or test the subs that make up the script. If you want to test the script, then an external test would be more appropriate, e.g. a shell script. If you want to test the functions that make up the script, then you can either write those tests as more functions within the script or refactor the elements into a Perl module and test the module (which you say you don't want to do).

    If the script is small enough, then refactoring might not be necessary. Simply add a '-test' command line argument and call into a test sub, which in turn tests everything else. If doing this, I like to print out a progress indicator of some kind (e.g. a '.' for every test that passes).

    If the script is more complex, though, you may want to consider refactoring bits into one or more modules and testing them with Test::Simple or Test::More.

    0 讨论(0)
  • 2021-02-01 05:52

    (I do not want to split the script into a separate module and the “executable”, since I plan to distribute the script as a single file.)

    Most people stitch files together like this at build time. App::Ack on the CPAN is an example of something that can be built like this.

    If you really want to test your application properly, you need to put the functionality in a module, and then write a Test::More-based test script that exercises the functions that the module provides. Then the actual script is just a thin wrapper around the module, usually something like:

    #!/usr/bin/env perl
    use Your::Class;
    Your::Class->new(args => \@ARGV)->run;
    

    See also: MooseX::Getopt.

    0 讨论(0)
提交回复
热议问题