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

Dear Monks,

I'm creating tests (using Test::More) for a perl application that previously had no tests defined for it. In the application itself, are many candidates for the tests that I am creating. Some of these are simple (and I'm not sure what the term for it is) such as permissions to write to a directory. Would it be considered bad style, good style, six of one, to replace the tests in the code with calls to my Test elements?

Eg. replace a line such as:
if (! -d $config_dir) { die "Missing directory $config_dir"; }
with
runtests("t/DirectoryExistence.t") || die "Missing directory $config_dir";

I don't ever anticipate the program existing without the tests, so it seems like it would be a suitable approach. It gives me the same result and I don't duplicate my efforts but it doesn't feel quite right. TIA, X.

Replies are listed 'Best First'.
Re: Using Test modules in production scripts
by jethro (Monsignor) on Feb 14, 2011 at 22:17 UTC

    Listen to your feelings ;-). The tests in t/ should test your code and not do the work of the code itself.

    Tests should be an independent instance that declares your code as correct, even after you changed parts of it or it is run on a different platform or your operating system is a new version. The important word is "independent". In your example you would write a test to check whether a missing directory produces an error message. If this test fails you know that that line doesn't work anymore in your script

    Note it makes not much sense adding tests to old applications, unless you plan to rewrite, enhance or refactor the application, or adapt it to new environments

      Hello Jethro,

      Thanks so much for your input, this makes sense.

      In truth, it's not really an old application, however it is already complete and it works correctly.
      It's never been in production though, it isn't well tested :), and the development environment is not the same system as the production environment. So I figured late tests are better than no tests.

      TIR, X.
Re: Using Test modules in production scripts
by ELISHEVA (Prior) on Feb 14, 2011 at 22:36 UTC

    The main reason not to go this route is that you take away the caller's control over what gets spit out in the case of a test failure What if the caller simply wants to know that the file failed to open and can try another file or just tell the user? Would you really want to log a bunch of TAP output spitting out at the terminal even when the caller considered the exception irrelevant or capable of recovery?

    Secondly, I don't see tests outside of a program as duplication at all. They have a very different purpose. When I write tests I'm usually testing a wide variety of inputs to a function. I don't assume an exception is bad, rather I may deliberately provoke exceptions. I want to test to make sure that an exception is thrown when conditions warrant it. Ironically, in some cases a test is passed only when the exception is thrown.

    Perhaps your actual goal here is logging? If so, I think you might be better off acquainting yourself with a module like Log::Log4Perl which gives you a permanent record (log file) and a lot of control over how much or how little output is generated and where it is stored.

    Or maybe you are inspired in this direction because of the rich assortment of assertions that have already been programed for you and wrapped in test modules? In some cases these can be had without using the test module. For example, Data::Compare can compare arbitrary Perl data structures and Data::Match compares your structure against a pattern.

      Hello Elisheva,

      Thank you for your advice.

      My goal is to provide testing such that the application can be deployed to a new platform and problems will be caught before it has a chance to damage anything.
      This question came to mind because I'm using the app tests to write the t/ tests. Perhaps I could simply reduce the amount of duplicated code between the two. Having test code in two locations means that I'll have to maintain test code in two locations.
      It seems youwin's suggestion in post # 888082 is probably the correct approach for reducing the redundant test code. If the t/ tests are sufficient, the tests in the app will be unnecessary.

      Thanks Again. X.

        xssnark:

        For production deployments, I've been toying around with having the script automatically run the test suite any time the script is newer than the name of the test script. So when I modify a program or module, it will automatically run the test suite. Only after I'm satisfied with my changes do I touch the test script. If I accidentally make a change without updating my test script, I'm immediately alerted by the fact that it runs the test suite. (Note: my toy scripts that I've been experimenting with don't prevent the script from running, it just runs the test suite before normal operation.)

        ...roboticus

        When your only tool is a hammer, all problems look like your thumb.

        Not a good idea. The tests are run at deployment, but what if someone deletes that directory later? Then your application doesn't work correctly anymore.

        You are optimizing at the wrong place. That directory test costs you about 30 bytes of hard disk space and about 100 microseconds per run of your application (probably less since the directory is accessed later on). If you think this is wasted time and space, you should switch to machine language programming.

        I just wrote a script last week where I tried to test everything twice if possible so as to make sure no error condition escaped unnoticed. It was a script to format and fill a SD-card, so for example I had two different ways to get the size of the device, just to be sure I don't make a mistake here.

        As long as tests are not in time-critical parts of your application, they are your best friends, an asset and a pillow for a peaceful sleep.

Re: Using Test modules in production scripts
by locked_user sundialsvc4 (Abbot) on Feb 14, 2011 at 23:37 UTC

    What you are dealing with is the problem of how to effectively test legacy code.   There has, in fact, been a large amount of material published over the years on this very topic, and you should carefully review some of it before proceeding.

    Perhaps the first question you should consider is ... what are you testing for?   And, why?   In a later post you suggest that one reason might be that you intend to port this application to another operating environment and therefore need to ascertain whether it will run there.   You should carefully consider, and enumerate, all of these motivations.

    It has been said, with regard to legacy code, that the question is not whether the code works “correctly,” but whether or not it now works “differently.”   The tests for an existing application might be focused, for example, on how the program deals with its environment, and how its responses vary given different sets of inputs.   Tests that try to delve into the mysteries of “mysterious code that (according to the business...) is working,” might not be appropriate at all, especially given the very real risk of de-stabilizing it.   (And thus, ex minimis, of invalidating your tests.)

    There are various strategies ... “black box,” “white box,” “glass box,” “mock testing,” and many more ... which are properly beyond the scope of this reply.   Time to do some googling, first.

      P.S.:   I am sensitive to the fact that the above post (and some of my others) might have come across wrongly ... as know-it-all, condescending, off-topic etc.   It was not intended to be so.   Anyone with comments, thoughts, suggestions etc. please /msg me privately.

Re: Using Test modules in production scripts
by youwin (Beadle) on Feb 14, 2011 at 22:29 UTC

    Dont do that, I think its bad style.

    You might be able to remove the file/directory existance tests in the code, if you ran the tests beforehand and everything worked out.

      Only if you are sure you absolutely need the (very) few cycles they take, and that nothing else on the system - including the sysadmin - could ever conceivably remove/alter the file/directories in question.