Perl,字符串,浮点数,单元测试和regexps!

时间:2011-02-09 22:30:34

标签: perl

好的,作为前言,这个问题可能比我正常的问题更“愚蠢” - 但是这个问题在过去几天一直让我讨厌,所以无论如何我都会问它。我将举例说明我的问题是什么,所以我希望将其概括为我当前的问题。

#!/usr/bin/perl -w use strict;

use Test::More 'no_plan';

my $fruit_string = 'Apples cost $1.50';
my ($fruit, $price) = $fruit_string =~ /(\w+)s cost \$(\d+\.\d+)/;

# $price += 0; # Uncomment for Great Success
is ($price, 1.50, 'Great Success');

现在运行时我收到消息

#   Failed test 'Great Success'
#          got: '1.50'
#     expected: '1.5'

要使测试工作 - 我要么取消注释注释行,要么使用is ($price, '1.50', 'Great Success')。这两个选项对我都不起作用 - 我正在使用Test :: Deep和cmp_deeply测试大量嵌套数据。我的问题是,如何从正则表达式中提取双精度然后立即将它作为双精度使用 - 或者如果有更好的方法让我知道 - 并随意告诉我从事园艺或其他事情,学习Perl是硬。

5 个答案:

答案 0 :(得分:10)

您已经在使用Test::Deep,,因此您只需使用num()包装器执行数字而不是逐字符串比较(它甚至可以添加公差,用于比较两个不精确的浮点值):

cmp_deeply(
    $result,
    {
        foo         => 'foo',
        bar         => 'blah',
        quantity    => 3,
        price       => num(1.5),
    },
    'result hash is correct',
);

对于单独进行的正常比较,cmp_ok会有效,但num()仍可用:cmp_deeply($value, num(1.5), 'test name')仍然有效。

答案 1 :(得分:1)

强制$price被解释为数字:

is ( 0 + $price, 1.50, 'Great Success');

答案 2 :(得分:1)

为什么不使用经过验证的ok?你将测试你真正想要测试的东西,而不必担心is是否做了太微妙或太聪明的事情。

ok($price == 1.5, 'Great Success');

is会对失败提供一些额外的诊断,但这也很容易与ok一起使用

ok($price == 1.5, 'Great Success') or diag("Expected \$price==1.5, got $price");

答案 3 :(得分:1)

您的测试失败,因为is($x, $y, $name)等同于cmp_ok($x, 'eq', $y, $name)eq强制将其每个参数计算为字符串。由于您希望数字相等,因此可以使用cmp_ok使用'=='将其写出来。您可以通过编写自己的is数字版本来简化操作:

sub is_num {cmp_ok $_[0], '==', $_[1], $_[2]}

但是这个版本被巧妙地打破了,它会在错误的行上报告错误。要确保错误报告显示正确的行:

sub is_num {splice @_, 1, 0, '=='; goto &cmp_ok}

goto &sub的原因是cmp_ok使用caller来确定错误发生的位置。 goto &sub语法会删除is_num的调用框设置,以便cmp_ok认为从is_num所在的位置调用它。

最后,我的模块Test::Magic的插件为Test::More提供语法糖:

use Test::Magic 'no_plan';

... # setup code

test 'fruit price',
  is $price == 1.50;

将其解释为cmp_ok( $price, '==', 1.50, 'fruit price')

答案 4 :(得分:0)

这种行为的原因是使用eq进行比较,这会强制对其参数进行字符串化。 1.50字符串化为'1.5',这会失败。

您的选择是与行为(强制字符串化或数字化)一起生活,或者编写您自己的替代方案,如果双方在回到eq比较之前看起来像是数字,那么将在数字上进行比较。我个人会采用后一种方法。