2016-12-15 2 views
1

서브 리턴 값에 관해 나에게 명확하지 않은 무언가가 있습니다. 저는 서브 모듈별로 모듈을 테스트하고 케이스가 발생할 경우 올바른 반환 값을 출력하는지 아니면 올바른 예외가 발생하는지 확인하고 싶습니다. 예를 들어서브 루틴의 성공/실패를 평가하십시오

, 이제 나는 다음과 같은 코드가 있다고 가정 해 보자 (X는 :: 인수가 :: BadFormat 예외 예외에서 파생 된 핸들러 :: 클래스) : 테스트 파일에서

package My::Module; 

    use strict; 
    use warnings; 

    sub new{#does things unrelated to the current question} 

    sub my_sub { 
     my ($self,$possible_value) = @_; 

     if ($possible_value =~ q{\w}) { #Affect value to current object 
      $self->{field} = $possible_value; 
     }else{ #throw an exception 
      X::Argument::BadFormat->throw(
       arg    => 'possible_value', 
       expected_format => 'something that looks like a word', 
       received_value => $possible_value, 
      ); 
     } 
    } 

, 나는 테스트를 실행합니다 같은 :

my $object = My::Module->new(); 
throws_ok(sub {$object->my_sub('*')}, 'X::Argument::BadFormat', 'Faulty value will raise an exception'); 
ok($object->my_sub('turlututu')); 

이 때 테스트하기 쉽습니다 : 보조가 값을 반환

  • ,
  • 시험 조건은 그냥 현재 객체에서 필드의 값을 설정할 때

그러나, 나는 아무것도 반환 할 이유가 없다, 예외를 발생해야합니다. 이 경우

:

  • 코드의 간단한 실행이 충분이 "true"로 보조 출력을 평가하는 것입니다?
  • 명시 적으로 "return 1;"을 추가해야합니까? ?
  • sub가 실제로 마지막 평가를 반환합니까?이 경우 성공은 "if"에서
  • 테스트의 성공입니까? 내가 생각하지 못했지만, 누구에게나 이 분명합니까?
+1

왜 객체의 속성이 getter를 통해 직접 attr을 통해 올바르게 설정되었는지 확인하는 것이 좋을까요? 예 :'my $ p = 'blah'; $ obj-> my_sub ($ p); $ obj -> {field}, $ p, "my_sub()는 필드 attr을 ok로 설정합니다;" – stevieb

+0

참으로. 나는 내 질문을 다르게 표현해야한다는 것을 알았다. 실제 문제는 필드 영향뿐만 아니라 서브 루틴이 값을 반환하지 않을 때마다 서브 루틴이 올바르게 종료되었는지 평가할 수있게하는 것입니다. 이게 더 명확한가요? –

+0

오. 질문을 읽고, 나는 일반적인 대답과 같은 것은 없다는 것을 이해한다? 내 반환 값에 대해 명시 적이어야하거나 내 개체에 대해 수행해야하는 동작을 테스트해야합니다. –

답변

2

없이, 당신이 마지막으로 실행 된 것입니다 $ POSSIBLE_VALUE의 값을 반환합니다, 귀하의 경우에는

return; 

로 끝나야합니다 값을 반환 할 필요가 없습니다 하위. 이것은 돌아 오는 것이 유용한 것처럼 보이지 않습니다.

당신이 명시 적으로 수익을 추가 가정 :

귀하의 throws_ok 테스트가 잘 보인다. 그런 다음 필드가 올바르게 설정되었는지 테스트해야합니다. 하위가 아무 것도 반환하지 않으므로 ok 테스트가 필요하지 않습니다.

+0

하지만주의 할 점으로, '$ possible_value'는'true '로 평가되고 다른 경우에는 false로 평가 될 수 있습니다. 나는 그게 좋다고 확신하지 못하고 명백한 수익을 선호하는 경향이 있습니다. – Sobrique

+0

@Sobrique 나는 항상 * 노골적인 반환을 선호한다. – ysth

+0

고맙습니다. 분명히 명확해야하고 밀도가 높다고해서 유감입니다. 마지막에 명시적인 retuner를 추가하면 ok() 테스트가 true로 평가됩니까? 아니면이 테스트를 사용하지 않아야합니까? –

3

이 경우 개체의 특성이 올바르게 설정되었는지 확인해야합니다. 그게 바로이 특별한 하위입니다. 설정이 정상이면 서브가 올바르게 종료되었습니다. 설정되지 않은 경우 하위 항목이 끝나기 전에 무언가 잘못되었습니다.

my $p='blah'; 
$obj->my_sub($p); 

is $obj->{field}, $p, "my_sub() set the field attr ok"; 

는 캡슐화를 위반하지 않을 수 있도록 field 속성이 게터가 있다면 그것은 더 나은 것,하지만 난 빗나가 다.

+0

감사합니다. 객체를 올바르게 수정했는지 확인하고 마법의 일반적인 평가 방법이 있는지 궁금한 점을 지적 할 것입니다. –

1

Perl은 기본적으로 마지막으로 실행 된 코드의 결과를 반환합니다. 예를 들어

:

print main(); 

sub main { 
    my $var = 9 * 7; 
} 

print 출력 할 것이다 (63).코드가 주어진 서브 루틴의 출력에 영향을받을 수 있다면 반환 값을 설정해야합니다 (일반적으로 서브 루틴/메소드 끝에서 항상 명시 적 리턴을 설정하는 것이 가장 좋습니다).

print main(); 

sub main { 
    my $var = 9 * 7; 
    return; 
} 

print은 아무 것도 출력하지 않습니다.

개인적으로 나는 항상 서브 루틴이 돌아 오는 상황에 따라 반환 값을 설정하려고 시도하지만 다른 사람들이 사용할 코드를 작성하는 경우 일반적으로 return;을 수행하는 것이 가장 안전합니다.

펄 :: 평론가 (link to the specific policy)에서 추가 설명 :

서브 루틴 "주"근처 라인 8에서 "반환", '서브 주요 {'로 끝나지 않습니다.

서브 루틴 :: RequireFinalReturn return', 잉어 ', croak', 다이', exec', 출구 ', goto', or 던져'(심각도 : 4)

다음은 중 하나를 명시 적으로 종료하는 모든 서브 루틴이 필요합니다.

말미에 명시적인 return 문이없는 서브 루틴은 일 수 있습니다. 반환 값이 이 될 것임을 추론하는 것은 어려울 수 있습니다.

또한 프로그래머가 중요한 반환 값을 의미하지 않고 return 문을 생략하면 서브 루틴의 내부 데이터 중 일부가 외부로 유출 될 수 있습니다. 이 경우를 생각해보십시오.

package Password; 
    # every time the user guesses the password wrong, its value 
    # is rotated by one character 
    my $password; 
    sub set_password { 
     $password = shift; 
    } 
    sub check_password { 
     my $guess = shift; 
     if ($guess eq $password) { 
      unlock_secrets(); 
     } else { 
      $password = (substr $password, 1).(substr $password, 0, 1); 
     } 
    } 
    1; 

이 경우 check_password()의 마지막 문이 할당입니다. 그 할당의 결과는 암시 적 반환 값이므로 잘못된 이 올바른 암호를 반환합니다. `return; 그것의 끝에서 서브 루틴이 문제를 해결합니다.

허용되는 유일한 예외는 빈 서브 루틴입니다.

이 정책에서 확인 된 문제를 수정할 때는주의하십시오. 맹목적으로하지 마십시오 `return; 모든 서브 루틴의 끝에있는 명령문.

+0

Perl :: Critic 견적에 대한 링크를 포함해야합니다. – simbabque

+1

커맨드 라인에서'perlcritic -1 --verbose 11'을 실행 시켰습니다.하지만 여기에있는 모듈의 cpan 페이지가 있습니다 : [Perl :: Critic :: Policy :: Subroutines :: RequireFinalReturn] (http : // search.cpan.org/~thaljef/Perl-Critic/lib/Perl/Critic/Policy/Subroutines/RequireFinalReturn.pm) – interduo