4

나는 최근에 간단하지만 심한 버그를 발견했습니다. 나는 목록이 있었고 가장 작은 회원을 찾고 싶었습니다. 나는 Python에 내장 된 min()을 사용했다. 모든 이상한 시나리오에서 목록이 비어있을 때까지 (내가 예상 할 수없는 이상한 사용자 입력으로 인해) 훌륭하게 작동했습니다. 내 응용 프로그램이 ValueError (BTW - 공식 문서에 문서화되어 있지 않음)와 충돌했습니다.Python 커버리지가 실패 할 때 예외에 대한 사전 테스트

나는 매우 광범위한 단위 테스트를 실시하고 있으며 정기적으로 이와 같은 예기치 않은 결과를 피하기 위해 조사를 실시하고 있습니다. 또한 Pylint (모든 것이 PyDev에 통합되어 있음)를 사용하고 경고를 무시한 적은 없지만 사용자가하기 전에이 버그를 발견하지 못했습니다.

내 방법론에서 을 변경할 수 있습니까? 이러한 종류의 런타임 오류가 발생하지 않도록하려면 어떻게해야합니까? (Java/C#에서는 컴파일 타임에 발견 되었습니까?).

큰 try-except로 코드를 래핑하는 것 이상을 찾고 있습니다. 그 밖의 무엇을 할 수 있습니까? 파이썬 함수에서 다른 많은 빌드가 이렇게 불쾌한 놀라움을 숨기고 있습니까 ???

+0

조금 명확히하기 위해 GRUB : 나는 최소/최대 생각하지 않습니다 없음 또는 0을 반환해야합니다.이 경우 예외를 발생시키는 것이 좋습니다. 나는 단지 내가 알지 못했던 테스트를 거치지 않은 숨겨진 경로를 찾았다 고 우려하고있다. 그리고 코드는 사용자로부터 지금까지 제거되었다 : 그것은 자연스러운 언어 여행 요청이다. 나는 모든 자료를 추출한다. 어떤 시점에서 나는 텍스트에서 한 지점까지 100km 반경에서 가장 큰 도시를 찾으려고 노력하지만 사용자가 옆에 0 개의 도시가있는 호주 공항에 들어갔다 ... 물론 나쁘다 ... –

+0

잠재적 인 대답 : 예외를 발생시키는 원인이되는 빈리스트를 전달하지 않으면 부분적으로 덮여있는 것으로 보이는이 라인을 보여주기위한 커버리지를 향상시킨다! 그런 식으로 보도 내용 보고서에 나타날 것이고 나는 그것을 다루는 시험을 쓸 것이다. 그게 가능하니? –

답변

5

Java/C#에서도 예외 클래스 인 RuntimeError는 선택되어 있지 않으므로 컴파일러에서 발견되지 않습니다 (RuntimeError가 아닌 CompileError).

Python에서 KeyboardInterrupt와 같은 특정 예외는 프로그램에서 임의의 지점에서 실제로 발생 될 수 있으므로 특히 털이 있습니다.

큰 try-except로 코드를 래핑하는 것 이상을 찾고 있습니다.

아무 것도 부탁드립니다. 자동으로 오류를 전달하는 대신 예외가 사용자에게 전달되고 프로그램이 중단되도록하는 것이 훨씬 좋습니다 (Zen of Python).

Java와 달리 Python에서는 모든 예외를 포착해야하므로 프로그래머가 빈 예외 처리기를 작성하여 예외를 무시하는 것이 너무 쉽기 때문에 모든 예외를 포착 할 필요가 없습니다.

그냥 휴식을 취하십시오. 사용자가 신고 할 수 있도록 수정할 수 있습니다. 또 다른 대안은 비어있는 필수 예외 처리기로 인해 고객의 데이터가 모든 곳에서 손상되기 때문에 디버거를 42 시간 동안 사용하는 것입니다.

따라서 방법론을 변경하려면 예외가 잘못되었다고 생각하는 것이 좋습니다. 그들은 꽤 아니지만 대안보다 낫다.

+0

나는 100 % 동의하고 이것이 내가 사용하는 방법론이다. 그러나 나는 단위 테스트를 실행할 수있는 커버리지 툴을 갖고 싶었고 코드 (예 : 예외)를 통해 특정 경로를 경험 한 적이 없다고 알려줍니다. –

0

귀하의 질문에 대한 직접적인 답변을 모르겠습니다. 나는 필립트가 그러한 가능성에 대해 경고한다면 나는 그것을 좋아할 것이다. 빈 목록은 모든 상황에서 문제를 일으키는 나의 일반적인 관행은 그것을 사용하기 전에 진실에 대한 목록을 확인하는 것입니다. 자주 어쨌든 None를 확인하기 위해 필요하기 때문에이 '무료'입니다

val = min(vals) if vals else 0 

많은 경우에 예를 들면 다음과 같습니다. 또한 새로운 스레드, 프로세스 또는 데이터베이스 트랜잭션을 시작하여 0 항목을 처리하는 것을 피하기 위해 특별한 경우 빈 목록에 성능 측면에서 성과를 낼 수 있습니다.

+1

downvoting하지 않지만 목록이'[1,0,3,2,5]'일 경우 어떻게해야합니까? 이제 유효한 최소값과 빈 목록으로 인해 발생하는 값을 구분할 수있는 방법이 없습니다 (구조에서). – ChristopheD

+0

@ChristopheD : 그것은 생각입니다. 자주, 특히 여기 * 분 *, 빈 또는 심지어 없음 목록은 실제로 문제가되지 않습니다. 이 경우 종종 직관적으로 사용하는 0과 같은 값이 있습니다. 코드를 작성할 때 None을 다루는 것만 큼 많이 알고 있습니다. 불행히도 '더 많은 경계'는 지금까지만 진행되므로이 ​​질문에 대한 진정한 대답은 아니라고 인정합니다. – DNS

+1

최소/최대 http://bugs.python.org/issue7153에 센티널을 추가하는 방법에 대한 토론이 있었지만 여러 가지 이유로 거부당했습니다. –

7

문제는 잘못된 형식의 외부 입력이 프로그램을 손상 시켰습니다. 이 솔루션은 코드 경계에서 가능한 입력 시나리오를 철저히 테스트 할 수 있습니다. 당신은 당신의 단위 테스트가 광범위하다고 말합니다.하지만이 가능성을 테스트하지 않았습니까?코드 커버리지는 유용한 툴이지만, 코드를 다루는 것은 완전히 테스트하는 것과 동일한 이 아니라이라는 것을 기억하는 것이 중요합니다. 철저한 테스트는 사용 시나리오와 코드 라인의 조합입니다.

내가 사용하는 방법은 내부 발신자를 신뢰하지만 외부 발신자 또는 입력을 신뢰하지 않는 것입니다. 그래서 명시 적으로 외부 입력을받는 첫 번째 기능을 넘어서는 코드에서 빈 목록의 경우 단위 테스트를 수행하지 마십시오. 하지만 그 입력 기능은 이어야하며,을 완전히 포함해야합니다.

이 경우 라이브러리의 예외는 합리적인 행동이라고 생각합니다. 빈 목록의 min을 요청하는 것은 의미가 없습니다. 예를 들어 네거티브 숫자를 처리 할 수 ​​있으므로 라이브러리에서 0과 같은 값을 정당하게 설정할 수 없습니다.

빈 목록은 min을 요청하는 코드에 도달해서는 안됩니다. 입력시 식별되어야하며 예외가 발생했거나 해당 예외가 발생했을 경우 0으로 설정해야합니다. 그것이 당신을 위해 일한다는 것입니다.

+0

자연 언어를 다루는 재미있는 점은 잠재적 인 입력을 철저히 다루는 것 근처에서 아무 것도 할 수 없다는 것입니다. 그것은 내가 처리해야하는 현실입니다. 라이브러리 동작에는 아무런 문제가 없습니다 (문서화되지 않았 음을 제외하고!). –

1

당신은 무작위 테스트를 사용할 수도 :

#!/usr/bin/env python 
import random 
from peckcheck import TestCase, an_int, main 

def a_seq(generator): 
    return lambda size: [generator(size) 
         for _ in xrange(random.randrange(size))] 

class TestMin(TestCase): 
    def testInputNoThrow(self, x=a_seq(an_int)): 
     min(x) 

if __name__=="__main__": 
    main() 

peckcheck 설치하려면 다음을 입력합니다

$ pip install http://github.com/downloads/zed/peckcheck/peckcheck-0.1.v2.6.tar.gz 

하거나 peckcheck.py

+0

테스트가 임의성에 의존하게되면서 나는 정말로이 팬이 아닙니다. 당신은 씨앗을 제공함으로써 의사 무작위성을 사용할 수 있습니다 : http://stackoverflow.com/questions/9023660/how-to-generate-a-repeo-random-number-sequence – seanp2k

+0

@ seanp2k : 당신은 무작위 테스트의 요점을 놓치고 있습니다. . 결정 론적 테스트 (* 또한 무작위 테스트에 추가)를 원할 경우 테스트 입력을 하드 코드 할 수 있습니다. – jfs

관련 문제