好的,作为前言,这个问题可能比我正常的问题更“愚蠢” - 但是这个问题在过去几天一直让我讨厌,所以无论如何我都会问它。我将举例说明我的问题是什么,所以我希望将其概括为我当前的问题。
#!/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是硬。
答案 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比较之前看起来像是数字,那么将在数字上进行比较。我个人会采用后一种方法。