Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Test::More, is it possible to test a subroutine that exit()'s at the end?

I have a module that I wrote with some utility functions.

One of the functions is just a usage statement (recommended by user @zdim)

use 5.008_008;
use strict;
use warnings;

# Function Name:        'usage'
# Function Inputs:      'none'
# Function Returns:     'none'
# Function Description: 'Prints usage on STDERR, for when invalid options are passed'
sub usage ## no critic qw(RequireArgUnpacking)
{
    require File::Basename;
    my $PROG = File::Basename::basename($0);
    for (@_)
    {
        print {*STDERR} $_;
    }
    print {*STDERR} "Try $PROG --help for more information.\n";
    exit 1;
}

I know the subroutine works as expected, and it's simple enough to test, but... For coverage reports, I'd like to include it in my unit tests. Is there any way to test it using Test::More?

like image 244
Speeddymon Avatar asked Dec 24 '17 23:12

Speeddymon


2 Answers

You can use Test::Exit.

If for any reason you cannot use it, just copy the code below:

our $exit_handler = sub {
    CORE::exit $_[0];
};

BEGIN {
    *CORE::GLOBAL::exit = sub (;$) {
        $exit_handler->(@_ ? 0 + $_[0] : 0)
    };
}

{
    my $exit = 0;
    local $exit_handler = sub {
        $exit = $_[0];
        no warnings qw( exiting );
        last TEST;
    };

    TEST: {
       # Your test here
    }

    cmp_ok($exit, '==', 1, "exited with 1");
}

Be sure to load your module after the BEGIN block.

like image 64
tinita Avatar answered Sep 21 '22 16:09

tinita


Alternatively, you can use END block to handle exit calls.

Inside an END code block, $? contains the value that the program is going to pass to exit(). You can modify $? to change the exit value of the program.

usage();

END {
    use Test::More;
    ok($?);
    done_testing();
}

Demo: https://ideone.com/AQx395

like image 22
Chankey Pathak Avatar answered Sep 18 '22 16:09

Chankey Pathak