Search code examples
perlunit-testingsubroutine

Evaluating the success/failure of a subroutine


There's something quite unclear to me about subs return value. I like to test my modules, sub by sub, and check whether they issue the correct return value or the correct exception if the case arise.

For example, let's say I have the following code (X::Argument::BadFormat is an exception handler derived from Exception::Class):

    package My::Module;

    use strict;
    use warnings;

    sub new{#does things unrelated to the current question}

    sub my_sub {
        my ($self,$possible_value) = @_;

        if ($possible_value =~ q{\w}) { #Affect value to current object
            $self->{field} = $possible_value;
        }else{ #throw an exception
            X::Argument::BadFormat->throw(
                arg             => 'possible_value',
                expected_format => 'something that looks like a word',
                received_value  => $possible_value,
            );
        }
    }

In the test file, I will run tests such as:

my $object = My::Module->new();
throws_ok(sub {$object->my_sub('*')}, 'X::Argument::BadFormat', 'Faulty value will raise an exception');
ok($object->my_sub('turlututu'));

It is easy to test when:

  • the sub returns a value,
  • the test conditions must raise an exception,

However, when I just set the value of a field in the current object, I have no reason to return anything.

In that case:

  • is the simple execution of the code enough to evaluate the sub output as "true" ?
  • Shall I add an explicit "return 1;" ?
  • does the sub actually return the last evaluation, in this case the sucess of the
  • test in the "if"? Something else I did not think about but which is obvious to everybody?

Solution

  • A sub that has no need to return a value should end with

    return;
    

    In your case, without it, you will be returning the value of $possible_value, which is the last thing executed. This doesn't look like a useful thing to return.

    Assuming you add the explicit return:

    Your throws_ok test looks fine. You should then test that the field was correctly set. Your ok test isn't needed, since your sub won't be returning anything.