[英]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.