2011-02-09 4 views
5

좋아요, 서문으로이 질문은 내 정상적인 질문 수준보다 '어리 석음'입니다. 그러나이 문제는 지난 며칠 동안 나를 성가 시게 했으므로 어쨌든 물어볼 것입니다. 내 문제가 무엇인지에 대한 모의 예를 드리겠습니다. 그래서 현재 문제에 대한 일반화를 기대할 수 있습니다. 내가 하나가 주석 행의 주석을 해제 또는 is ($price, '1.50', 'Great Success')을 사용 -이 실행되는 지금펄, 문자열, 수레, 단위 테스트 및 정규식!

#!/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' 

테스트 작업을하려면 메시지가 표시됩니다. 두 가지 옵션이 모두 작동하지 않습니다. Test :: Deep 및 cmp_deeply를 사용하여 방대한 양의 중첩 데이터를 테스트하고 있습니다. 제 질문은 어떻게 정규 표현식에서 double을 추출한 다음 즉시 double으로 사용 할 수 있습니까? 아니면 더 좋은 방법이 있다는 것을 알려주는 것이지요. 그리고 Perl을 배우면서 gardening이나 lol을 가져 가라고 말해도됩니다. 단단한.

+0

문자열을 숫자와 비교하므로 문자열로 비교됩니다. 나는 네가 그걸 가지고 무엇이든 할 수 있다고 생각하지 않는다. –

답변

10

로 해석됩니다 당신은 이미 당신은 단순히에 num() 래퍼를 사용할 수 있습니다 Test::Deep,를 사용하는 문자열 식 비교가 아닌 숫자를 수행하십시오 (두 개의 부정확 한 부동 소수점 값을 비교하기 위해 허용 오차를 더할 수도 있습니다) :

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

@Platinum Azure : 아니요, 번호를 추가해야합니다. 그것을 테스트하십시오. – btilly

+0

그래, 난 그냥 perlop 다시 확인하고 당신 말이 맞아. 어쩌면 펄 6이나 뭔가 생각하고있을거야. –

+1

내 게시물에 명시된 바와 같이 cmp_deeply를 사용하고 있으므로 0 + $ price를 효과적으로 사용할 수 없습니다. 0 + $ price를 수행하려면 현재 코드 전체를 거쳐 모든 변수에 적용해야합니다. 두 배가되어야합니다. –

0

이유는 즉, 비교를 할 EQ를 사용하여 자사의 인수의 문자열 화 (stringification)을 강제하는 것입니다. 1.50은 '1.5'로 문자열 화되며 이는 실패합니다.

당신의 선택은 행동 (강요 문자열 또는 숫자)과 함께 살거나 다른 방법으로 숫자를 비교할 수있는 자신 만의 대안을 쓰는 것입니다. 나는 개인적으로 후자의 접근 방식을 택할 것이다.

1

ok을 사용해 보시지 않겠습니까? 실제로 테스트하려는 것을 테스트 할 것이며, is이 너무 미묘하거나 너무 영리한 작업을하고 있는지 걱정할 필요가 없습니다.

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

is 실패에 대한 몇 가지 추가 진단을 제공한다,하지만 너무

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

'ok'는 실패한 어설 션의 경우에 예상 값과 주어진 값을 제공합니다. – Tim

1

is($x, $y, $name)cmp_ok($x, 'eq', $y, $name)에 해당하기 때문에 귀하의 테스트가 실패 ok와 함께 할 수있을만큼 간단합니다. eq은 각 인수가 문자열로 평가되도록합니다. 숫자 평등을 원하기 때문에, '=='을 사용하여 cmp_ok으로 작성할 수 있습니다. 이 잘못된 줄에 오류를보고합니다,

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

하지만 그 버전은 미묘하게 분류됩니다 : 당신은 is의 자신의 숫자 버전을 작성하여 일을 더 쉽게 만들 수 있습니다. 오류보고 오른쪽 라인을 보여줍니다 있는지 확인하십시오 : cmp_ok 오류가 발생한 위치를 확인하기 위해 caller을 사용하기 때문에 goto &sub에 대한

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

이유입니다. goto &sub 구문을 사용하면 is_num에 대한 호출 프레임 설정이 지워지고 위치에서 cmp_ok이 호출되고 있다고 생각됩니다.

마지막으로, Test::More에 대한 문법 설탕을 제공 내 모듈 Test::Magic의 플러그 :

use Test::Magic 'no_plan'; 

... # setup code 

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

cmp_ok($price, '==', 1.50, 'fruit price')

+0

'goto' 대신'local $ Test :: Builder :: Level = $ Test :: Builder :: Level + 1; '을 사용하여 실패한 테스트가보고되는 위치를 변경해야합니다. – Ether

+0

@Ether => Perl이 투명하게 디스패치하는 일반적인 목적의 방법을 제공 할 때 API 관련 솔루션을 사용해야하는 이유는 무엇입니까? '$ Test :: Builder :: Level'을 설정해야하는 경우가 있습니다 (하나의 호출 사이트에서 여러 개의 테스트를 실행하거나 테스트 작업을 수행하는 경우). 그러나 이것들 중 하나가 아닙니다. –