http://www.perlmonks.org?node_id=1226824

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

Hello folks!

I'm writing a lot of test nowadays (finally!) and currently I have a lot of duplicated code in them. This is because I'm testing a simple backup solution and many tests of mines requires backup scenarios to be present in a temporary folder.

So I create and delete files and folders in my tests, I read a write files permissions etc.. and to accomplish these tasks I use CPAN modules not needed by my module but only during tests.

1) I can have a dedicated module with all required modules imported an exposing all subs I need. Where? How? Where the dependencies of this (somehow private module) have to be specified? In the BUILD_REQUIRES in the Makefile.PL of the main module?

2) have a special part of the main module (or a dedicated package?) loaded only during tests? How to trigger this behaviour?

3) (probably worst approach) build only one test file, a big one with all modules used and all subs defined in the very same file

I did not found anything related to the matter (maybe because of generic terms of the search..) nor advice in my bibliotheca and asking in the chatter box I had a precious suggestion by Corion that i'll present below (for future readers) but I also want to know from you other possible approaches or tecniques, and if i missed some detail:

Corion suggested option 1: and pointed me to his WWW-Mechanize-Chrome's helper.pm testing module. The solution is simple and worth to share (I see # hide from CPAN indexer can some elaborate this?).

Have you other approach? Some quirk I missed? Something to pay attention to?

thanks

L*

There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

Replies are listed 'Best First'.
Re: code duplicate in tests -- code or custom module only needed to test
by hippo (Bishop) on Dec 06, 2018 at 11:51 UTC

    If you have dependencies which are required only by the tests then it is important to flag them as such. If you use ExtUtils::MakeMaker then TEST_REQUIRES is the key. This has the following benefits:

    • Users who don't want to run the tests do not end up downloading and installing modules they won't use (ie. if the test dependencies had been declared as main dependencies).
    • Users who can't successfully install the test dependencies can still run your module.
    • Your tests don't bloat the main code.

    FWIW, I agree with Corion and haukex that option 1 is likely to be the best path.

Re: code duplicate in tests -- code or custom module only needed to test
by haukex (Archbishop) on Dec 06, 2018 at 10:59 UTC

    I would recommend against the options 2 and 3 you mentioned - for 2 because I wouldn't place any special "test mode" code into the main module, since you end up testing something different from the code that the user actually ends up running. Adding a test library has the least issues IMO, the only thing to keep in mind is that if it contains complex functions, those should be tested as well, which it's fine to do as part of the test suite. Have a look at the t folder in any of my distros, https://metacpan.org/author/HAUKEX - although I admit I figured some of it out myself, so I'm not saying everything I did there is a best practice :-)

    Update: Dependencies for tests are specified via TEST_REQUIRES in Makefile.PL.

    Update 2: Regarding "hide from CPAN indexer", see e.g. https://www.effectiveperlprogramming.com/2012/04/hide-namespaces-from-pause/

Re: code duplicate in tests -- code or custom module only needed to test
by 1nickt (Canon) on Dec 06, 2018 at 13:09 UTC

    Hi,

    (I see # hide from CPAN indexer can some elaborate this?).

    Suppose you end up doing as suggested and add a test module to your distro. Maybe you want to update your tests from time to time but not release a new version of the distro. You can push files to PAUSE and avoid having them indexed as a new version if you either:

    • Put a linebreak in your package declaration, like:
      package Foo::Bar;
    • Use the no_index directive in your META.yml or META.json file.
    For more, see https://github.com/andk/pause/blob/master/doc/operating-model.md section 3.5.

    Hope this helps!


    The way forward always starts with a minimal test.
Re: code duplicate in tests -- code or custom module only needed to test
by markong (Pilgrim) on Dec 06, 2018 at 12:33 UTC
    I'm writing a lot of test nowadays (finally!) and currently I have a lot of duplicated code in them. This is because I'm testing a simple backup solution and many tests of mines requires backup scenarios to be present in a temporary folder.

    I'd just add that this seems like a perfect situation to upgrade to some xUnit-like test framework, e.g.: Test::Class to prevent code duplication. As a bonus you get also Test(startup) and Test(shutdown) subs to wrap your tests in some particular "environment" without leaving garbage around once finished.