Warning: lots of magic ahead!

My colleague came up with a question regarding a very special case of unit testing and I'm not sure how to answer it.

My response was the clean approach is to refactor the code into additional subs called from the "printers" returning the data structures and test those nested "units".

Obviously the code would be easier to maintain and reusable.

So I suggested a "dirtier" approach to use a constant TEST to flag that tests are running and to safe the desired code into package variables named "$PKG::TEST_something" (or probably $PKG::TST::Something)

The advantage is that every code conditioned by ... if TEST won't show up in production code.

Here a condensed demo in a single file, the output of B::Deparse shows that the TEST code disappears. (In a real test.t file the "PKG::TEST" flag has to be set before requiring the module PKG to be effective)

Question Is there a better way to do this?

# set TEST flag before compiling tested module use constant 'PKG::TEST' => 1; # ### here normally use PKG { package PKG; use strict; use warnings; use Data::Dump qw/pp dd/; use v5.16; sub create_output { my $count =shift; my $string; my $fh; my %hash; # create (mildly) complex demo HoA $hash{$_} = [reverse 1.. $count--] for "a".."f"; # memorize datastructure when testing $PKG::TEST_result = \%hash if TEST; my $target = "c:/tmp/output.txt"; # redirect filehande to string when testing $target = \$PKG::TEST_content if TEST; open $fh, '>', $target; # Output to "file" print $fh pp \%hash; } } # ### my tests package main; use B::Deparse; use Data::Dump qw/pp dd/; # prove that TEST code disappears unless TEST is true print B::Deparse->new->coderef2text(\&PKG::create_output); PKG::create_output(5); if ( PKG::TEST ) { use Test::More; my $expected ={ a => [5, 4, 3, 2, 1], b => [4, 3, 2, 1], c => [3, 2, 1], d => [2, 1], e => [1], f => [], }; is_deeply( $PKG::TEST_result, $expected, "internal result" ); my $expected_str = pp $expected; is( $PKG::TEST_content, $expected_str, "file output" ); done_testing(); }

The problems I see:

Cheers Rolf
(addicted to the Perl Programming Language :)
Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

*) a case were inlining would be nice, more about that in a future post

update

added comments to code


In reply to "deep" unit testing by LanX

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.