This is more of an idle thought than a serious need, but in trying to clean up a test suite, I realized that I had a bit of a problem. In this particular test suite, the modules are loaded and remain memory-resident when moving from test class to test class (xunit style testing but with hand-rolled test software.) As a result, if I alter the behavior of any actual code, I must be sure to restore that behavior when I'm done lest other test classes use the altered behavior and fail mysteriously. More than once we have a test class pass when run by itself but fail when run with another class. This is part of the obstacle that I face.

One of the problems with the test suite is that it frequently outputs a lot of data that's not part of the test output. Warnings get spit out, log messages are written to STDOUT and STDERR, etc. When a test suite takes over an hour to run, no one's going to sit there and read all of those, so I'm capturing them and testing their output. For one class, here's what I've done (setup and teardown methods are called at the beginning and end of each test in the class):

my $LOG_ERROR; + my $_log_error_sub_cache; sub setup { my $class = shift; $class->SUPER::setup_test; $_log_error_sub_cache = *RTK::Digitrak::LogRun::_log_error{CODE}; no warnings 'redefine'; *Foo::Bar_log_error = sub($) { $LOG_ERROR = shift }; } + sub teardown { my $class = shift; $class->SUPER::teardown_test; no warnings 'redefine'; *Foo::Bar:_log_error = $_log_error_sub_cache; }

In my individual tests, I can now test that the $LOG_ERROR has the error message that I expect. I have to restore the original sub in the teardown or else the next test class that's run will have the altered behavior and this is bad because it will hide the data that I need to test.

What I would like to do is something like this:

use Foo::Test::LogMessages; my $log = Foo::Test::LogMessages->new; sub TEST_WHICH_HAS_LOG_OUTPUT { # do something $log->capture_log_only_for_this_scope; is($log->message, qw/some message/, '... and we should have an error +'); } sub TEST_WHICH_DOES_NOT_HAVE_LOG_OUTPUT { # do something }

The idea here is that I only want the side effect of suppressing the log message in particular subs. I could put a $log->end_capture_log or something similar at the end of the test sub but if a programmer forgets to do that, we could have plenty of log messages get suppressed and not even realize it. If somehow the log capturing routine could recognize the scope that it's in and disable itself when it's done, that would be handy. This would sort of be like local *Foo::Bar = sub { ... };, but without wanting to deal with all of the explicit typing or the typos inherent in dealing with full package names.

Cheers,
Ovid

New address of my CGI Course.


In reply to "local" side effects by Ovid

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.