2011-09-29 4 views
3

RealClass를 사용하는 모듈을 사용하고 있으므로 액세스 할 수없는 내부 종속성이 있습니다.테스트를 위해 Python의 모듈에서 클래스를 어떻게 스텁링합니까?

테스트를 위해 RealClass의 기능을 대체하는 FakeClass를 만들 수 있기를 원합니다. 나는 개별적인 방법 대신 전체 수업을 대체하고 싶지 않다.

내가 뭘 원하는지 보이는 stubble을 보았지만 Mox 또는 다른 조롱하는 프레임 워크에이 기능이 있는지 궁금해하고 있었습니까? 아니면 무엇을 사용 하시겠습니까? 어쩌면 fudge, 원숭이 패치? 이 물건으로 베스트 프랙티스를 찾고 있습니다. 또한 유용한 예는 대단합니다.

의사 코드 :

from module import RealClass 

class FakeClass 
    methodsFromRealClassOverridden 

class Test(unittest.TestCase): 
    setup() 
    teardown() 

test1() 
    stub(RealClass, FakeClass) // something like this, but really just want the functionality 
    classThatUsesRealClass // now will use FakeClass 

UPDATE :

여기에 내가 그것을 발견 한 방법입니다. 완벽하지는 않지만 작동합니다.

예 : 나는 당신이 그렇게 난 그냥 내 2 센트를주는거야 의견/경험을 원한다고 생각

fake = FakeClass() 
stub = stubout.StubOutForTesting() 
stub.Set(RealClass, 'method_1', fake.method_1) 
stub.Set(RealClass, 'method_2', fake.method_2) 
+0

당신도 '조롱'을 보게 될 수도 있습니다. – Daenyth

+0

나는 조롱을 필요로하지 않으며 메소드를 호출 할 필요가 없으며 실제로 스터 빙 기능이 필요합니다. – dre

+0

'From FakeClass from FakeClass from RealClass'와 같은 것이 당신을 위해서 일할 것입니까? –

답변

6

.

몇 가지 Python 테스트 도구/클래스/프레임 워크가 있지만 대부분의 경우 Python의 단순성/역 동성/개방성을 고려하면 대부분의 경우 Python의 스터 빙을 포함하는 특수 관련 테스트 케이스를 사용하는 것으로 제한됩니다. 인터페이스 레벨, 그리고 unittest ... 프레임 워크를 사용하기 전까지.

이 테스트/스터 빙을 수행하기에 관해서 특히 원숭이 패치에 대한 경멸 아무것도 없다 :

#!/usr/bin/env python 
# minimal example of library code 

class Class: 
    """ a class """ 
    def method(self, arg): 
     """ a method that does real work """ 
     print("pouet %s" % arg) 

#!/usr/bin/env python 
# minimal example for stub and tests, overriding/wrapping one method 
from Class import Class 

Class._real_method = Class.method 
def mymethod(self, arg): 
    # do what you want 
    print("called stub") 
    # in case you want to call the real function... 
    self._real_method(arg) 
Class.method = mymethod 

# ... 

e = Class() 
e.method("pouet") 
당신이 ... 수입 모듈의 내부에 수입 된 모듈의 내부에 물건을 패치 할 수

네임 스페이스

위의 방법은 C 모듈의 클래스에서는 작동하지 않습니다. getattr/setattr을 사용하여 클래스 멤버 이름을 필터링하는 래퍼 클래스를 사용할 수 있으며 래퍼 클래스에서 재정의 된 멤버를 반환 할 수 있습니다. 당신이 임시 테스트를 수행 피곤되고 나면

#!/usr/bin/env python 
# Stupid minimal example replacing the sys module 
# (not very useful/optimal, it's just an example of patching) 

import sys 

class SysWrap(): 
    real = sys 
    def __getattr__(self, attr): 
     if attr == 'stderr': 
      class StdErr(): 
       def write(self, txt): 
        print("[err: %s]" % txt) 
      return StdErr() 
     print("Getattr %s" % attr) 
     return getattr(SysWrap.real, attr) 

sys = SysWrap() 
# use the real stdout 
sys.stdout.write("pouet") 
# use fake stderr 
sys.stderr.write("pouet") 

, 당신은 당신이 (그루터기, 퍼지) 유용 언급 한 것과 같은 높은 수준의 물건을 찾을 수 있지만, 그들을 즐길 당신이이 효율적으로 사용하기 먼저 그들이 해결 한 문제점을 확인하고 두포에서 수행하는 모든 자동 작업을 수락하십시오.

ad-hoc 원숭이 패치의 일부가 남아있을 가능성이 높습니다. 이해하기 쉽고 모든 도구에는 몇 가지 제한이 있습니다.

도구는 힘을 실어 주지만 효율적으로 사용하려면 도구를 이해해야합니다.

도구를 사용할지 여부를 결정할 때 중요한 점은 코드 묶음을 전송할 때 테스트 도구를 포함한 전체 환경을 전송한다는 것입니다. 테스트 도구가 너무 복잡하기 때문에 다음 사람이 당신만큼 영리하지 못하고 테스트를 건너 뛸 수 있습니다. 일반적으로 소프트웨어에서 많은 종속성을 사용하지 않으려합니다.

결국, 당신이 물건을 사용한다면 unittest 및 ad-hoc 테스트/원숭이 패치 만 사용하면 아무도 신경 쓰지 않을 것입니다. 코드가 이 아니 어서 어쨌든 복잡한 것일 수 있습니다.

+0

정보 및 예제 주셔서 감사합니다, 내가 직면하는 문제는 sys 모듈이 다른 모듈/클래스 내에서 호출됩니다 있지만 unittest 직접 sys 모듈을 만들 수 없다는 것입니다. – dre

관련 문제