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

I am in the midst of refactoring a large application into several modules, on the theory that it will make it easier to package the application for use in different places if it is modularized.

One of the modules provides a frontend to Net::Telnet::Cisco to slurp up various tables from routers and switches. To do so it must log in to each router or switch using its telnet and enable passwords.

My question is: given the fact that it is problematic to do anything that prompts the user in a t/*.t script, and it is even more problematic to ask for the user to put passwords on the command line or in the environment (which in "make test" is often done from the command line anyway), how can I test these modules at all?

Net::Telnet::Cisco itself seems to get around the issue by using only a test.pl script (which doesn't have the same issues as a t/*.t script WRT the test harness eating the prompt). Can a given module use *both* test.pl and t/*.t?

As you can probably tell, I'm new to the Monastery and fairly new at writing modules as opposed to scripts. Any assistance will be appreciated. Thanks.

Replies are listed 'Best First'.
Re: Module testing using passwords
by adrianh (Chancellor) on Mar 06, 2004 at 00:10 UTC

    Ideas in no particular order...

    • Create mock router/switches and log in to those for testing rather than real ones. This has the bonus of allowing you to easily create error conditions.
    • If security issues make it a reasonable option, ask the user for test usernames/passwords in Makefile.PL/Build.PL and store them for the use of the test suite later. Module::Build has various built in mechanisms that make this very simple.
    • Get the test scripts to pick up the username/password from an environment variable. Skip the tests if it's not available.

    Hope this helps.

      Sounds good so far:
      • First point: We really don't have spare equipment to do this with, and I don't think I can make the assumption that a random sysadmin grabbing this from CPAN (should it end up there) will either. Perhaps you're talking about writing some sort of simulator?
      • I've been trying to avoid requiring Module::Build to be installed as a prerequisite for these packages (the main disadvantage of Module::Build over ExtUtils::MakeMaker is that it isn't (yet) included in the core).
      • As the module currently sits, I do use the environment variable method, and my main reason for posting was the concern that setting sensitive information like this in the environment is little to no more secure than having it on the command line. Indeed, environment variables are usually set on the command line, either in the make command or via setenv.

      This package should only be installed by network administrators and preferably on a server with only net admins as users. Perhaps a warning in the README to this effect, right under the part of the install instructions that describe the environment variables used, will suffice. On the other hand, it would likely be better to prompt if possible, just like Net::Telnet::Cisco does, and other replies indicate it does work.

      Thanks much.

      Update: forgot to put the URL in the link for Net::Telnet::Cisco, it's there now.

        We really don't have spare equipment to do this with, and I don't think I can make the assumption that a random sysadmin grabbing this from CPAN (should it end up there) will either. Perhaps you're talking about writing some sort of simulator?

        Yup, a simulator is what I'm talking about - have a google for mock objects. You can do similar things with external code/servers. For example I have some tests for some code that talks to sendmail that fires up my own binaries. Because you're using a simple simulator you make it do whatever you want, making it much easier to test error handling code (e.g. how would you test a "real" server aborting a connection half way through).

        I've been trying to avoid requiring Module::Build to be installed as a prerequisite for these packages (the main disadvantage of Module::Build over ExtUtils::MakeMaker is that it isn't (yet) included in the core).

        Fair point. For me the pain in having to reinvent the wheels that Module::Build provides now outweigh the pain of having to get yet another module installed. As ever YMMV :-)

Re: Module testing using passwords
by tachyon (Chancellor) on Mar 05, 2004 at 23:46 UTC

    Oops misread my own test case!!! Thanks adrianh

    No you can't Yes you can have test.pl and t/test.t and get both run AFAIK. The test dir/file is specified in the Makefile when you do perl Makefile.PL. If there is a t/ dir then that is what is used. If there is not a t/dir then test.pl is used.

    [root@devel3 test]# perl -MFile::Find -e 'File::Find::find( sub{print +$File::Find::name, $/, `cat $_`, $/,$/}, "." )'; cat: .: Is a directory . ./test.pl #!/usr/bin/perl use Test; BEGIN{plan tests => 1} ok(1); ./Makefile.PL use ExtUtils::MakeMaker; WriteMakefile( 'NAME' => 'T', ); ./T.pm package T; 1; cat: t: Is a directory ./t ./t/test_t.t #!/usr/bin/perl use Test; BEGIN{plan tests => 1} ok(1); [root@devel3 test]# perl Makefile.PL Writing Makefile for T [root@devel3 test]# make cp T.pm blib/lib/T.pm [root@devel3 test]# make test PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_h +arness(0, 'blib/lib', 'blib/arch')" t/*.t t/test_t....ok All tests successful. Files=1, Tests=1, 0 wallclock secs ( 0.02 cusr + 0.00 csys = 0.02 C +PU) PERL_DL_NONLAZY=1 /usr/bin/perl "-Iblib/lib" "-Iblib/arch" test.pl 1..1 ok 1 [root@devel3 test]# mv t t.ignore [root@devel3 test]# perl Makefile.PL Writing Makefile for T [root@devel3 test]# make [root@devel3 test]# make test PERL_DL_NONLAZY=1 /usr/bin/perl "-Iblib/lib" "-Iblib/arch" test.pl 1..1 ok 1 [root@devel3 test]# [root@devel3 test]# rm -f test.pl [root@devel3 test]# perl Makefile.PL Writing Makefile for T [root@devel3 test]# make [root@devel3 test]# make test No tests defined for T extension. [root@devel3 test]# [root@devel3 test]# mv t.ignore/ t [root@devel3 test]# perl Makefile.PL Writing Makefile for T [root@devel3 test]# make [root@devel3 test]# make test PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_h +arness(0, 'blib/lib', 'blib/arch')" t/*.t t/test_t....ok All tests successful. Files=1, Tests=1, 0 wallclock secs ( 0.01 cusr + 0.01 csys = 0.02 C +PU) [root@devel3 test]#

    cheers

    tachyon

      No you can't have test.pl and t/test.t and get both run AFAIK

      Actually, if you have both the default behaviour is to run both. Look at the results of that first make test again :-)

      Not that this is relevant to the OP as far as I can see...