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

I'm new to testing. I've got a test that uses a call to a private method like so:

# Check that module loads data my $xyz_events = $checker->_get_event_data('arg'); my $is_hash_ref = ref $xyz_events eq 'HASH'; is $is_hash_ref, 1, 'returns a hash ref';

I'm thinking it's OK to break the rules a bit since I'm just running tests. It also seems like it makes writing tests easier by testing small components of the module. But I worry it's a sign that I'm going about testing in the wrong way. What is the opinion of the wiser Monks about this?

$PM = "Perl Monk's";
$MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate";
$nysus = $PM . ' ' . $MCF;
Click here if you love Perl Monks

Replies are listed 'Best First'.
Re: Testing private methods a no-no?
by davido (Cardinal) on May 20, 2016 at 14:46 UTC

    Organize your tests such that one group is testing the functionality of the class's public interface, and another group is testing the internal implementation. The internal implementation tests are more likely to become broken as the implementation evolves, but the public interface tests should be quite stable. And by separating them into different groups, it's easier to determine if the result of a change will be acceptable without a deprecation cycle.


    Dave

Re: Testing private methods a no-no?
by haukex (Archbishop) on May 20, 2016 at 14:32 UTC

    Hi nysus,

    Testing private methods is perfectly fine. As you say, often it's advantageous to test as small a unit as possible.

    If you have a class that has private methods, then having a test file that tests the private methods of that class is normal. On the other hand, what I personally would try to avoid is accessing other classes' private methods from tests - it's often a sign that your API might need some refactoring (like providing a public accessor for the data or even that a restructuring of the classes might help).

    Hope this helps,
    -- Hauke D

Re: Testing private methods a no-no?
by shawnhcorey (Friar) on May 20, 2016 at 20:40 UTC

    FYI: Did you know you can create truly private subs in Perl?

    # create a block to isolate the sub { local *foo = sub { print "foo\n"; }; # this works foo(); } # this does not work foo();

      Hello shawnhcorey,

      This is nice, but it’s probably cleaner to assign the subroutine reference to a lexical variable:

      { my $foo = sub { my ($n) = @_; print "foo($n)\n"; }; $foo->(1); # valid call } $foo->(2); # invalid call

      This has the advantage of changing the invalid call from a runtime error into a compiletime error.

      From Perl v5.18 on you can also use the experimental Lexical Subroutines feature.

      Update: Fixed typo in the code snippet.

      Hope that helps,

      Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      that was random