[英]Perl, strings, floats, unit testing and regexps!
好吧,作为序言,这个问题可能比我正常的问题更“愚蠢” - 但是这个问题在过去的几天一直让我讨厌,所以无论如何我都会问它。 我将举例说明我的问题是什么,所以我希望将其概括为我当前的问题。
#!/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是硬。
您已经在使用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')
仍然有效。
强制$price
被解释为数字:
is ( 0 + $price, 1.50, 'Great Success');
为什么不使用经过验证的ok
? 您会测试你实际上意味着测试,而不必担心是否件事is
做什么太微妙或太聪明了。
ok($price == 1.5, 'Great Success');
is
不提供故障一些额外的诊断,但是这是很容易与做ok
,太
ok($price == 1.5, 'Great Success') or diag("Expected \$price==1.5, got $price");
您的测试失败,因为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
的位置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')
这种行为的原因是使用eq进行比较,这会强制其参数的字符串化。 1.50字符串化为'1.5',这会失败。
您的选择是与行为(强制字符串化或数字化)一起生活,或者编写您自己的替代方案,如果双方在回到eq比较之前看起来像是数字,那么将在数字上进行比较。 我个人会采用后一种方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.