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

Hello Monks I have several perl scripts that I was told to write test suites for. The scripts look like this:
#!/usr/bin/perl -w # file somescript.pl use strict; use warnings; sub SubThatNeedsToBeTested { # do some stuff if ($error ) { print "error occurred\n"; exit 2; } if ($othererror) { print "another error occurred\n"; exit 3; } } sub NoNeedToTestThis { # ... } ## main program &SubThatNeedsToBeTested (); &NoNeedToTestThis (); exit 0;

I would like to write tests only for some functions, for example for SubThatNeedsToBeTested but not for NoNeedToTestThis.

Could this be achieved without restructuring the scripts ie moving functions like SubThatNeedsToBeTested to a separate module? Can I somehow load subs into my test script namespace without executing the main program part?

Some methods call exit $errorcode. Is there a way to trap this? I was thinking about eval, but it only traps die.

How would you test this without restructuring the scripts too much?

Thank you for your answers

Replies are listed 'Best First'.
Re: Testing parts of perl scripts
by ELISHEVA (Prior) on Feb 19, 2009 at 03:16 UTC
    I think you may find Test::Simple and Test::More helpful. This is the "standard Perl testing" to which Tanktalus is referring.

    The documentation in the above modules will tell you about the mechanics of writing tests. However, a more important issue is deciding what you want to test for. To plan that, you might want to walk yourself through the following steps:

    • Organization: organize your code into a form that can be easily tested in parts. Generally, this means moving the subroutines into a module file so that they can be called without causing the main script to be executed in toto. Statements outside of a subroutine get executed each time a script is run, so it is not very friendly to testing things "in parts". (Sorry, I know you were hoping for a different answer)
    • Investigation:
      • What are the input parameters to SubThatNeedsToBeTested?
      • What environmental factors are going to affect the behavior of SubThatNeedsToBeTested?
      • For each input parameter, what are the possible legal values? illegal values?
      • Does the function have a return value? What is the expected range of values? How should the return value behave in a scalar context? A list context? Is there a difference?
      • Does this function have intentional side effects (e.g. modifies global variables, system state)? What are they?
    • Development:
      • Develop a sample set of inputs - parameters and environmental variables. Make sure to include some with bad values as well as good values
      • For each sample set of inputs and calling context, predict the expected output and side effects.
      • Now write your script using the various test functions in Test::Simple and Test::More to verify that the actual return values of your function match the expected return values and that the expected side effects actually occur
      • Also be sure to include tests with bad inputs to verify that your function behaves as you want it to in the face of bad data.

    The above is a very general overview. Perhaps, if you could give us more information about the nature of the function that you are trying to test, we might be able to point you to some additional modules in CPAN that could make your testing life easier. For testing the impact of environmental factors, CPAN has several modules for creating mock environments and mock system components. If your outputs are complicated, there are also numerous modules available for testing and diagnosing errors in complex data structures and long strings.

    Best, beth

Re: Testing parts of perl scripts
by Tanktalus (Canon) on Feb 18, 2009 at 23:01 UTC

    Best answer is the one you've excluded: put all your functionality into module(s), and then use standard perl testing (./Build test or make test, via tests in t/*.t files) to load and test them.

    Next best would be to take your "main program" and put it into a function, say "do_main" so that all you're really doing is calling "do_main". And then it's trivial:

    do_main unless (caller);
    And then, in your test code, you can simply require "my-script.pl"; and you can call any function in there whatsoever.

Re: Testing parts of perl scripts
by locked_user sundialsvc4 (Abbot) on Feb 19, 2009 at 03:44 UTC

    Wow, Beth! What a jewel!!

    Test::Exception is also useful. Generally, these scripts would be easier to test (and to use...) if they were modules (packages). Then you would have a very well-defined and isolated context for testing.

    Try to move your organization into the idea that testing is development, and that it ain't over until the tests (which are designed first...) run clean and stay clean. You'll have a lot more weekends to yourself.