加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

perl – 获取模块中明确定义的方法/函数列表

发布时间:2020-12-15 21:45:46 所属栏目:大数据 来源:网络整理
导读:在工作单元测试中实现代码覆盖的悲伤状态后,我正在尝试创建一个实用程序,它将扫描我们的代码库并标记没有100%的文件.我找到了两种获得所有方法的方法: 直接访问符号表: for my $classname ( @ARGV ) { eval "require $classname"; die "Can't load $class
在工作单元测试中实现代码覆盖的悲伤状态后,我正在尝试创建一个实用程序,它将扫描我们的代码库并标记没有100%的文件.我找到了两种获得所有方法的方法:

直接访问符号表:

for my $classname ( @ARGV ) {
   eval "require $classname";
   die "Can't load $classname $EVAL_ERROR"
      if $EVAL_ERROR; 

    no strict 'refs';
    METHODS:
    for my $sym ( keys %{ "${classname}::" } ) {
       next METHODS unless defined &{"${classname}::${sym}"};
       print "$symn";
   }
}

使用CPAN的Class::Inspector模块:

for my $classname ( @ARGV ) {
   my @methods = Class::Inspector->methods($classname,'public');
   print Dumper @methods;
}

这两种方法产生了类似的结果;这些问题是它们显示了整个模块可用的所有方法,而不仅仅是该模块内部定义的方法.

有没有办法区分模块可访问的方法和模块内部明确定义的方法?

注意:我没有尝试创建完整的代码覆盖率测试,对于我的用例,我只想测试所有方法至少被调用过一次.像Devel::Cover这样的完整覆盖测试对我们来说太过分了.

解决方法

每个子(或更具体地说,每个CV),记住它最初声明的包.测试用例:

Foo.pm:

package Foo;
sub import {
  *{caller . "::foo"} = sub{};
}
1;

Bar.pm:

package Bar;
use Foo;

our $bar;  # introduces *Bar::bar which does not have a CODE slot
sub baz {}
1;

现在访问符号表会同时提供foo和baz.顺便说一句,我会写这样的代码(原因会在稍后变得清晰):

my $classname = 'Bar';
for my $glob (values %{ "${classname}::" }) {
   my $sub = *$glob{CODE} or next;
   say *$glob{NAME};
}

接下来,我们必须查看B module以反省underlying C data structure.我们使用B :: svref_2object函数执行此操作.这将生成一个B :: CV对象,该对象具有方便的STASH字段(返回具有NAME字段的B :: HV对象):

use B ();
my $classname = 'Bar';
for my $glob (values %{ "${classname}::" }) {
   my $sub = *$glob{CODE} or next;
   my $cv = B::svref_2object($sub);
   $cv->STASH->NAME eq $classname or next;
   say *$glob{NAME};
}

添加一些健全性检查,这应该很好.

不应通过字符串eval完成动态类/模块加载.相反,我推荐Module::Runtime

Module::Runtime::require_module($classname);

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读