Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to isolate from installed libraries in hg repo for testing?

Tags:

perl

How can I use local hg repo libraries for testing isolating from already installed libs?

Installed production perl package and local hg repo has the same structure

    +-- lib
        |-- modA.pm
        |-- modB.pm
    +-- bin
        |-- example.pl
    +-- t
        |-- modA.t
        |-- modB.t

libraries installed at and the path is added to @PERL5

/nfs_share/perl/
env|grep -i perl
PERL5:/usr/local/perl:/nfs_share/perl

local hg repo at:

/data/user/hg/perl

modB.pm

#!/usr/bin/perl
use modA;
sub modB_compare{
    my (x,y) = @_;
    # .....
    return x-y;
}

bin/example.pl

use FindBin qw($Bin);
use lib "${Bin}/lib/";
use modA, modB;
# if this call is from local lib
my $result = modB_compare(x,y);
# if sub being called from production or local hg?
my $result2 = modA_method();
# from local hg repo or from production lib?!

If I were to modify and test in local hg repo, there is no gurantee that the lib I called is from local repo, not from the production libs.

What is the potential solutions for isolation the libraries for testing in a local hg repo?

like image 943
Gang Avatar asked Dec 30 '15 14:12

Gang


1 Answers

Short answer: for tests, just use prove -l.

If I were to modify and test in local hg repo, there is no gurantee that the lib I called is from local repo, not from the production libs.

Actually, there is, for the problem you've defined.

If you know that ./lib/modA.pm exists and ./lib/ in @INC, then ./lib/modA.pm will be loaded and any system perl version won't be*.

Your use lib statement does this for you as documented in perlvar @INC and require.

However, for tests, it's normal practice not to use lib, but instead use the -I flag in perl (perl -Ilib t/modA.t) or, better, prove, which also has a -l flag, so you can just do prove -l and it runs all the tests in t/ using the modules in ./lib.

NB: You might also want to look into ExtUtils::MakeMaker or Module::Build::Tiny which help with distribution tasks, and you might want to consider Dist::Zilla or (for a quicker start) Dist::Milla

If you just want to verify what's going on You can check which files have been loaded in use or require statements by looking at %INC.

If you absolutely have to control what modules are accessible, for instance because you want to test different behaviour depending on whether third-party modules are installed (rather than your own code), I suggest looking into perlbrew. This will help you compile your own perl (of almost any vaguely recent version) which does not use the libraries from system perl, but instead has its own libraries, using local::lib; you can then switch between multiple installed perls. The only exceptions are libraries that are packaged with perl itself; you can get a list of these from Module::Corelist.

Finally, you might want to check out Carton. I don't think it's quite what you're asking for but it's such a similar problem domain that I think it's worth a mention.


* OK, strictly, lib has to appear in @INC before the system perl lib directories, because what happens is that perl goes through @INC in order and finds files corresponding to the package name you have asked it to load; all of the methods you've used and that I'm talking about in this answer will make sure that your lib directory appears earlier in @INC then your system perl libs.

like image 168
user52889 Avatar answered Nov 16 '22 01:11

user52889