重构perl sub以获得可测试性

jev*_*rth 4 perl refactoring unit-testing

我继承了一个perl代码库.考虑以下子程序;

sub getSysRTable
{
    my $iface = shift;
    return if not length($iface);
    my %ip_routes;
    my @routes = `/usr/bin/netstat -rn`;
    foreach my $route(@routes) {
        if ($route =~ /([\S.]+)\s+([\d.]+.[\d.]+.[\d.]+.[\d.]+)\s+(UGS|UGHS)\s+($iface)/ )
            { $ip_routes {$1} = $2 }
    }
    return %ip_routes;
}
Run Code Online (Sandbox Code Playgroud)

我想为这段代码编写单元测试.我想到的测试将使用来自的样本输出netstat -rn并检查预期的行为.sub as is,调用一个命令,因此使用此实现注入我的测试数据是有问题的.

为了测试性而重构这个子的惯用方法是什么?

ike*_*ami 5

首先,更改您的代码如下:

sub getDataForSysRTable {
    return `/usr/bin/netstat -rn`;
}

sub getSysRTable
{
    my $iface = shift;
    return if not length($iface);
    my %ip_routes;
    my @routes = getDataForSysRTable();
    foreach my $route(@routes) {
        if ($route =~ /([\S.]+)\s+([\d.]+.[\d.]+.[\d.]+.[\d.]+)\s+(UGS|UGHS)\s+($iface)/ )
            { $ip_routes {$1} = $2 }
    }
    return %ip_routes;
}
Run Code Online (Sandbox Code Playgroud)

那么为了你的测试,你可以做到

local *getDataForSysRTable = sub { 
   ... return known data ...
};

my $ip_routes = getSysRTable($iface);
Run Code Online (Sandbox Code Playgroud)

  • 对于模拟子程序,我更喜欢使用http://search.cpan.org/~gfranks/Test-MockModule-0.11/lib/Test/MockModule.pm (2认同)