Unit test that checks for "croak"

F

freesoft12

Hi,

I have a module that calls 'croak' if the input argument to my
function is wrong. I want to write a unit test that tests if 'croak'
is called when I give a bad input.

---- PathUtils.t ----
use Test::More qw( no_plan );
use PathUtils;

my $path = '/a/b/../c';
deleteDoubleDotsInPath(\$path);
ok($path eq '/a/c'); # success test

$path = '../c'; # bad input. a fail/negative test

# how can write a 'ok()' or 'is()' that checks that 'croak' function
is called
# ok(deleteDoubleDotsInPath(\$path));

------------ end ----------

----------- PathUtils.pm ----------

package PathUtils;
use Carp;
require Exporter;

our @ISA = qw(Exporter);
our @EXPORT = qw(&deleteDoubleDotsInPath);

# This function removes the double dots in a path '..' eg: a/b/../c/
d/../e
sub deleteDoubleDotsInPath {
my $text = shift;
die "Malformed path" if !check_path_($text);

while($$text =~ m/\.\./) {
$$text =~ s/\/[^\/]*\/\.\.//;
}
}

sub check_path_ {
my $text = shift;

my @dirs = split(/\//,$$text);
my @double_dots = grep(/\.\./,@dirs);
if (scalar(@dirs) - scalar(@double_dots) > scalar(@double_dots)) {
return 1;
}
return 0;
}
------------ end ------------

Regards
John
 
U

Uri Guttman

fc> I have a module that calls 'croak' if the input argument to my
fc> function is wrong. I want to write a unit test that tests if 'croak'
fc> is called when I give a bad input.

croak is just a wrapper around die so catch the die with a block eval.

fc> $path = '../c'; # bad input. a fail/negative test

fc> # how can write a 'ok()' or 'is()' that checks that 'croak' function
fc> is called
fc> # ok(deleteDoubleDotsInPath(\$path));

first call the code in a block eval and then check if $@ is set (which
means the code called die somewhere). <untested>

eval { deleteDoubleDotsInPath(\$path) } ;

ok( !$@, 'delete double dots' ) ;

uri
 
D

Dr.Ruud

Uri said:
first call the code in a block eval and then check if $@ is set (which
means the code called die somewhere). <untested>

eval { deleteDoubleDotsInPath(\$path) } ;

ok( !$@, 'delete double dots' ) ;

I promote to test the return value of eval.

eval {
deleteDoubleDotsInPath( \$path) };
1;
}
or do {
$@ ||= "unknown error";
...
};
 
T

Tim Greer

^^^^^^^
what do you mean?

Probably he promotes that method of doing it, unless it meant propose.
^^^
what does this do?

Principal Skinner -- A conjunction meaning "in the event that" or "on
condition of".

(I know that doesn't apply. Sorry, I couldn't help it.)

The ||= is just an assignment operator (give it a (probably default)
value, if it doesn't already exist).

It will assign $@ the value 'unknown error' if it doesn't have a value
already.

(defined are to allow or ignore the zero value, otherwise use without
defined if that suits your needs)

I.e., $@ is $@ (defined) or else 'unknown error'.

I.e., $@ = $@ || 'unknown error'.

I.e., $@ = 'unknown error' if ! defined $@.

I.e., $@ = 'unknown error' unless defined $@.

I.e., if (a conjunction meaning "in the event that") $@ is undefined,
that 'unknown error' will be the assigned value.


.... or, were you asking something else?
 
D

Dr.Ruud

Tim said:
Probably he promotes that method of doing it, unless it meant propose.

I mean "promote". There are known issues in Perl with $@, like $@
loosing a value, like with DESTROY.
I already proposed @@, so $@[-1] would hold the last one.

And I just hate the decoupled way of "if ($@){}", it is far too distant
for my taste. The Perl compiler needs to do crazy things to try to make
$@ to be about the previous statement (or block) as much as possible.
 
T

Tim Greer

Dr.Ruud said:
Tim said:
Probably he promotes that method of doing it, unless it meant
propose.

I mean "promote". There are known issues in Perl with $@, like $@
loosing a value, like with DESTROY.
I already proposed @@, so $@[-1] would hold the last one.

And I just hate the decoupled way of "if ($@){}", it is far too
distant for my taste. The Perl compiler needs to do crazy things to
try to make $@ to be about the previous statement (or block) as much
as possible.

I assumed so (but thanks for clarifying), and I completely agree with
you on this matter as well.
 
S

sln

Tim said:
Probably he promotes that method of doing it, unless it meant propose.

I mean "promote". There are known issues in Perl with $@, like $@
loosing a value, like with DESTROY.
I already proposed @@, so $@[-1] would hold the last one.

And I just hate the decoupled way of "if ($@){}", it is far too distant
for my taste. The Perl compiler needs to do crazy things to try to make
$@ to be about the previous statement (or block) as much as possible.

Wait, I've known about this for along time. How to catch $@ in its pristine
state. Perhaps and ID, hooked to a state of eval, to be matched later.

sln
 
F

freesoft12

eval { deleteDoubleDotsInPath(\$path) } ;
ok( !$@, 'delete double dots' ) ;

uri

Hi,
Here is what I have done to solve the problem:

1) I added a special message in the 'croak' call:

sub deleteDoubleDotsInPath {
my $text = shift;
croak "Bad argument" if !check_path_($path_ref); # check validity of
argument
...
}

2) In the Test, I search for the message in the negative test:
# failure tests
$path = '../c'; # passing in a bad path
eval { deleteDoubleDotsInPath(\$path);};
ok($@ =~ m/Bad argument/,"Test Four"); # check if the message is what
we expect

Regards
John
 
P

Peter Scott

I have a module that calls 'croak' if the input argument to my function
is wrong. I want to write a unit test that tests if 'croak' is called
when I give a bad input.

use Test::Exception;

dies_ok { } ...

throws_ok { } ...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top