orphanBrent has asked for the wisdom of the Perl Monks concerning the following question:

Is there a way to test functions defined in a .pl file in a .t file using Test::Simple or Test::More? For example, I have a program called foo.pl which defines a function called bar(). I would like to have a test program, foo.t, test bar() for correctness. Can you do this or can you only test perl modules (.pm) in an external test file?

Replies are listed 'Best First'.
Re: Testing .pl files in Test::Simple
by rafl (Friar) on Mar 17, 2006 at 01:35 UTC

    Actually it doesn't matter which extension a file has. The content matters.

    Usually perl modules only contain some functions, classes, methods, whatever, that can be used from a script afterwards. Evaluating such a module doesn't execute code normally.

    That's different from common perl scripts, which actually do real work when being evaluated. You can include a script in another script as well (using require or do or whatever), but all the code inside the script will be executed as soon as it's being evaluated. Therefor it's not quite possible to include such a script somewhere else (in a test script, for example) just to be able to use functions that are defined by it.

    How to fix that?

    • Put the code that does the actuall work and needs to be tested in a module
    • Introduce some bad hacks in your script that make it possible to be included somewhere without being executed
      • For example make it only execute its stuff when it's called with a special parameter or whatever. This parameter will not be given when you only include the file somewhere
    • Make other cruel hacks that let you get the actual definition of the sub that needs to be tested to eval it in the test script and test if afterwards

    Of course there may be more possibilities, but I can't think of a clean solution that does not seperate the code that should be tested from the actual script.

    Cheers, Flo

      I agree with this post. For an example of how to do this, I recommend How a script becomes a module.

      To summarize part of that, if you really want to leave things as a script, the important thing is to write the script to allow it to be required like a module or run like a script. brian_d_foy calls this a "modulino". The key is to put all executable code into subroutines, but only execute the "main" function if there is no caller. This lets you require the modulino for testing, or to call it as a script.

      # File modulino.pl package My::Modulino; use strict; use warnings; __PACKAGE__->main() unless caller(); sub foo { # utility subroutine return "foo"; } sub main { # body of the script } 1; # require needs to be true

      Then you can test individual subroutines by loading it as a module:

      use Test::More tests => 2; require_ok( "modulino.pl" ); is( My::Modulino::foo(), "foo", "got foo" );

      Hope that helps.

      -xdg

      Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.