如何从hg repo中安装的库中隔离出来进行测试?

时间:2022-12-20 12:16:08

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

如何使用本地hg repo库来测试已安装的libs的隔离?

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

已安装的生产perl包和本地hg repo具有相同的结构

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

libraries installed at and the path is added to @PERL5

安装在库中的库和路径添加到@ PERL5

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

local hg repo at:

当地的hg repo:

/data/user/hg/perl

modB.pm

modB.pm

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

bin/example.pl

斌/ 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.

如果我要在本地hg repo中进行修改和测试,那么我没有保证我调用的lib来自本地仓库,而不是来自生产库。

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

什么是隔离库的可能解决方案在本地hg repo中进行测试?

2 个解决方案

#1


3  

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

简短回答:对于测试,只需使用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.

如果我要在本地hg repo中进行修改和测试,那么我没有保证我调用的lib来自本地仓库,而不是来自生产库。

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*.

如果您知道./lib/modA.pm存在且@INC中存在./lib/,那么将加载./lib/modA.pm并且任何系统perl版本都不会是*。

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

您使用lib语句为您执行此操作,如perlvar @INC和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.

但是,对于测试,通常的做法是不使用lib,而是在perl中使用-I标志(perl -Ilib t / modA.t),或者更好的是,证明,它也有-l标志,所以你可以证明-l并使用./lib中的模块运行t /中的所有测试。

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

注意:您可能还想查看有助于分发任务的ExtUtils :: MakeMaker或Module :: Build :: Tiny,您可能需要考虑Dist :: Zilla或(为了更快的开始)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.

如果您只想验证发生了什么您可以通过查看%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.

如果你必须控制哪些模块是可访问的,例如因为你想根据是否安装了第三方模块(而不是你自己的代码)来测试不同的行为,我建议你查看perlbrew。这将帮助您编译自己的perl(几乎任何模糊的近期版本),它不使用系统perl中的库,而是使用local :: lib;而是拥有自己的库。然后,您可以在多个已安装的perls之间切换。唯一的例外是与perl本身打包在一起的库;您可以从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.

最后,你可能想看看Carton。我不认为这是你所要求的,但它是一个类似的问题领域,我认为值得一提。


* 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.

*确定,严格来说,lib必须在系统perl lib目录之前出现在@INC中,因为发生的事情是perl按顺序通过@INC并找到与你要求它加载的包名相对应的文件;您在本答案中使用的所有方法都将确保您的lib目录早于@INC,然后是您的系统perl libs。

#2


2  

This is potentially a bit of a can of worms - because any time you try to maintain concurrent 'installed' versions, you can very easily trip over incorrect dependencies. It's doable, but you have to be particularly careful when making the switch that you're not accidentally using a 'wrong' version.

这可能是一些蠕虫病毒 - 因为每当您尝试维护并发“已安装”版本时,您都可以轻松地跳过错误的依赖项。这是可行的,但是在制作开关时你必须特别小心,因为你不会意外地使用'错误'版本。

As a result - for this sort of scenario, I'm using Docker. At risk of simplifying a bit, it's a way of packaging up your application instance with it's dependencies into a sort of mini virtual machine.

结果 - 对于这种情况,我正在使用Docker。有可能简化一点,这是一种将应用程序实例与其依赖关系打包成一种迷你虚拟机的方法。

You create an image from a docker file, which is quite similar to a make file, except it 'builds' into an image, that you can then run - which includes your application and all it's dependencies.

您可以从docker文件创建一个图像,该文件非常类似于make文件,除了它“构建”到一个图像中,然后您可以运行 - 包括您的应用程序及其所有依赖项。

I am also using Docker containers for my production instances, which I appreciate may not be a viable answer in your environment. But the point of me doing so is that I can develop to my heart's content, then when I'm ready for a release build a new 'reference' image to hand off to test.

我也在我的生产实例中使用Docker容器,我很欣赏这可能不适合您的环境。但我这样做的重点是,我可以发展到我心中的内容,然后当我准备好发布时,建立一个新的“参考”图像,以便进行测试。

If that ref image passes, then exactly the same image gets deployed into prod. Because it's self contained, and packaged with all it's dependencies, I get a high degree of confidence that I won't trip over on version skew of installed libs, nor will I get tripped up on a future update breaking anything - because everything my 'version' needs to run is part of the image.

如果该ref图像通过,则完全相同的图像被部署到prod中。因为它是自包含的,并且包含了所有它的依赖项,所以我非常自信我不会因为安装的库的版本偏差而绊倒,也不会因未来的更新而破坏任何东西 - 因为我的一切都是'版本'需要运行是图像的一部分。

But as a result, you have a very clean environment, and almost never have to worry about the things you're worrying about.

但结果是,你有一个非常干净的环境,几乎从不担心你担心的事情。

You can even fairly safely run your dev/ref/prod on the same physical tin, and just bind/map different resources (volumes/ports, etc.) to differentiate.

您甚至可以相当安全地在相同的物理锡上运行dev / ref / prod,并绑定/映射不同的资源(卷/端口等)以区分。

#1


3  

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

简短回答:对于测试,只需使用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.

如果我要在本地hg repo中进行修改和测试,那么我没有保证我调用的lib来自本地仓库,而不是来自生产库。

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*.

如果您知道./lib/modA.pm存在且@INC中存在./lib/,那么将加载./lib/modA.pm并且任何系统perl版本都不会是*。

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

您使用lib语句为您执行此操作,如perlvar @INC和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.

但是,对于测试,通常的做法是不使用lib,而是在perl中使用-I标志(perl -Ilib t / modA.t),或者更好的是,证明,它也有-l标志,所以你可以证明-l并使用./lib中的模块运行t /中的所有测试。

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

注意:您可能还想查看有助于分发任务的ExtUtils :: MakeMaker或Module :: Build :: Tiny,您可能需要考虑Dist :: Zilla或(为了更快的开始)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.

如果您只想验证发生了什么您可以通过查看%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.

如果你必须控制哪些模块是可访问的,例如因为你想根据是否安装了第三方模块(而不是你自己的代码)来测试不同的行为,我建议你查看perlbrew。这将帮助您编译自己的perl(几乎任何模糊的近期版本),它不使用系统perl中的库,而是使用local :: lib;而是拥有自己的库。然后,您可以在多个已安装的perls之间切换。唯一的例外是与perl本身打包在一起的库;您可以从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.

最后,你可能想看看Carton。我不认为这是你所要求的,但它是一个类似的问题领域,我认为值得一提。


* 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.

*确定,严格来说,lib必须在系统perl lib目录之前出现在@INC中,因为发生的事情是perl按顺序通过@INC并找到与你要求它加载的包名相对应的文件;您在本答案中使用的所有方法都将确保您的lib目录早于@INC,然后是您的系统perl libs。

#2


2  

This is potentially a bit of a can of worms - because any time you try to maintain concurrent 'installed' versions, you can very easily trip over incorrect dependencies. It's doable, but you have to be particularly careful when making the switch that you're not accidentally using a 'wrong' version.

这可能是一些蠕虫病毒 - 因为每当您尝试维护并发“已安装”版本时,您都可以轻松地跳过错误的依赖项。这是可行的,但是在制作开关时你必须特别小心,因为你不会意外地使用'错误'版本。

As a result - for this sort of scenario, I'm using Docker. At risk of simplifying a bit, it's a way of packaging up your application instance with it's dependencies into a sort of mini virtual machine.

结果 - 对于这种情况,我正在使用Docker。有可能简化一点,这是一种将应用程序实例与其依赖关系打包成一种迷你虚拟机的方法。

You create an image from a docker file, which is quite similar to a make file, except it 'builds' into an image, that you can then run - which includes your application and all it's dependencies.

您可以从docker文件创建一个图像,该文件非常类似于make文件,除了它“构建”到一个图像中,然后您可以运行 - 包括您的应用程序及其所有依赖项。

I am also using Docker containers for my production instances, which I appreciate may not be a viable answer in your environment. But the point of me doing so is that I can develop to my heart's content, then when I'm ready for a release build a new 'reference' image to hand off to test.

我也在我的生产实例中使用Docker容器,我很欣赏这可能不适合您的环境。但我这样做的重点是,我可以发展到我心中的内容,然后当我准备好发布时,建立一个新的“参考”图像,以便进行测试。

If that ref image passes, then exactly the same image gets deployed into prod. Because it's self contained, and packaged with all it's dependencies, I get a high degree of confidence that I won't trip over on version skew of installed libs, nor will I get tripped up on a future update breaking anything - because everything my 'version' needs to run is part of the image.

如果该ref图像通过,则完全相同的图像被部署到prod中。因为它是自包含的,并且包含了所有它的依赖项,所以我非常自信我不会因为安装的库的版本偏差而绊倒,也不会因未来的更新而破坏任何东西 - 因为我的一切都是'版本'需要运行是图像的一部分。

But as a result, you have a very clean environment, and almost never have to worry about the things you're worrying about.

但结果是,你有一个非常干净的环境,几乎从不担心你担心的事情。

You can even fairly safely run your dev/ref/prod on the same physical tin, and just bind/map different resources (volumes/ports, etc.) to differentiate.

您甚至可以相当安全地在相同的物理锡上运行dev / ref / prod,并绑定/映射不同的资源(卷/端口等)以区分。