문제

저는 대규모 코드 기반을 리팩토링하기 시작하는 프로젝트에 참여하고 있습니다.즉시 발생한 한 가지 문제는 각 파일이 다른 많은 파일을 가져오는 것입니다.단위 테스트 작성을 시작할 수 있도록 실제 코드를 변경하지 않고도 단위 테스트에서 이를 우아한 방식으로 모의하는 방법은 무엇입니까?

예로서:테스트하려는 기능이 포함된 파일은 Python 핵심 라이브러리가 아닌 소프트웨어의 일부인 10개의 다른 파일을 가져옵니다.

나는 가능한 한 별도로 단위 테스트를 실행할 수 있기를 원하며 지금은 가져오는 파일의 항목에 의존하지 않는 기능만 테스트하려고 합니다.

모든 답변에 감사드립니다.

처음부터 뭘 하고 싶은지 몰랐는데 이제는 알 것 같아요.

문제는 일부 가져오기가 일부 타사 자동 마법으로 인해 전체 응용 프로그램이 실행 중일 때만 가능하다는 것입니다.그래서 sys.path로 지적한 디렉토리에 이 모듈에 대한 스텁을 만들어야 했습니다.

이제 모듈 누락에 대한 불만 없이 단위 테스트 파일에 테스트를 작성하려는 함수가 포함된 파일을 가져올 수 있습니다.

도움이 되었습니까?

해결책

모듈을 가져 오려면 동시에 모듈을 가져 오지 않으려면 아무것도 가져 오지 않도록하는 경우 교체 할 수 있습니다. __import__ 내장 기능.

예를 들어이 클래스를 사용하십시오.

class ImportWrapper(object):
    def __init__(self, real_import):
        self.real_import = real_import

    def wrapper(self, wantedModules):
        def inner(moduleName, *args, **kwargs):
            if moduleName in wantedModules:
                print "IMPORTING MODULE", moduleName
                self.real_import(*args, **kwargs)
            else:
                print "NOT IMPORTING MODULE", moduleName
        return inner

    def mock_import(self, moduleName, wantedModules):
        __builtins__.__import__ = self.wrapper(wantedModules)
        try:
            __import__(moduleName, globals(), locals(), [], -1)
        finally:
            __builtins__.__import__ = self.real_import

그리고 테스트 코드에서 쓰기 대신 import myModule, 쓰다:

wrapper = ImportWrapper(__import__)
wrapper.mock_import('myModule', [])

두 번째 논쟁 mock_import 모듈 이름 목록입니다 하다 내부 모듈로 가져오고 싶습니다.

이 예제는 가져 오지 않는 대신 원하는 것보다 다른 모듈을 가져 오거나 자신의 사용자 지정 개체로 모듈 객체를 조롱하는 대신 원하는 것보다 다른 모듈을 가져올 수 있습니다.

다른 팁

Python 가져 오기 메커니즘으로 정말로 멍청이를 원한다면 ihooks 기준 치수. 동작을 변경하기위한 도구를 제공합니다 __import__ 내장. 그러나 왜 당신이 이것을 해야하는지 당신의 질문에서 명확하지 않습니다.

"다른 많은 파일을 가져옵니다"?사용자 정의된 코드 베이스의 일부인 다른 많은 파일을 가져오시나요?아니면 Python 배포판의 일부인 다른 많은 파일을 가져오나요?아니면 다른 오픈 소스 프로젝트 파일을 많이 가져오나요?

가져오기가 작동하지 않으면 "간단한" 방법이 있습니다. PYTHONPATH 문제.다양한 프로젝트 디렉토리를 모두 PYTHONPATH 테스트에 사용할 수 있는 것입니다.우리는 다소 복잡한 경로를 가지고 있습니다. Windows에서는 다음과 같이 관리합니다.

@set Part1=c:\blah\blah\blah
@set Part2=c:\some\other\path
@set that=g:\shared\stuff
set PYTHONPATH=%part1%;%part2%;%that%

우리는 (a) 사물의 출처를 파악하고 (b) 사물을 이동할 때 변경 사항을 관리할 수 있도록 경로의 각 부분을 별도로 유지합니다.

이후 PYTHONPATH 순서대로 검색되면 경로의 순서를 조정하여 사용되는 항목을 제어할 수 있습니다.

일단 "모든 것"을 갖게 되면 그것은 신뢰의 문제가 됩니다.

어느 하나

  • 무언가(예: Python 코드 베이스)를 신뢰하고 가져오기만 하면 됩니다.

또는

  • 당신은 무언가(즉, 자신의 코드)를 신뢰하지 않으며

    1. 별도로 테스트하고
    2. 독립형 테스트를 위해 모의합니다.

Python 라이브러리를 테스트하시겠습니까?그렇다면 할 일이 많습니다.그렇지 않다면 실제로 테스트하려는 항목만 조롱해야 할 수도 있습니다.

단위 테스트 전에 빠르고 간단한 수정을 원한다면 어려운 조작이 필요하지 않습니다.

단위 테스트가 테스트하려는 코드와 동일한 파일에 있는 경우 원치 않는 모듈을 삭제하세요. globals() 사전.

다음은 다소 긴 예입니다.당신이 모듈을 가지고 있다고 가정 impp.py 내용:

value = 5

이제 테스트 파일에 다음을 작성할 수 있습니다.

>>> import impp
>>> print globals().keys()
>>> def printVal():
>>>     print impp.value
['printVal', '__builtins__', '__file__', 'impp', '__name__', '__doc__']

참고하세요 impp 수입되었기 때문에 전 세계에 속합니다.함수 호출 printVal 사용하는 impp 모듈은 여전히 ​​작동합니다:

>>> printVal()
5

하지만 이제 제거하면 imppglobals()...

>>> del globals()['impp']
>>> print globals().keys()
['printVal', '__builtins__', '__file__', '__name__', '__doc__']

...그리고 전화를 걸어봐 printVal(), 당신은 얻을 것이다:

>>> printVal()
Traceback (most recent call last):
  File "test_imp.py", line 13, in <module>
    printVal()
  File "test_imp.py", line 5, in printVal
    print impp.value
NameError: global name 'impp' is not defined

...아마도 당신이 달성하려는 목표가 바로 이것이었을 것입니다.

단위 테스트에서 이를 사용하려면 테스트 스위트를 실행하기 직전에 전역 변수를 삭제할 수 있습니다.~에 __main__:

if __name__ == '__main__':
    del globals()['impp']
    unittest.main()

귀하의 의견에 ~ 위에, 특정 모듈을 이미 가져왔음을 Python에 확신시키고 싶다고 말합니다.이것은 여전히 ​​이상한 목표처럼 보이지만 이것이 정말로 원하는 것이라면 원칙적으로 가져오기 메커니즘 뒤에서 몰래 돌아다닐 수 있습니다. sys.modules.이것이 패키지 가져오기에 어떻게 작동하는지 잘 모르겠지만 절대 가져오기에는 괜찮을 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top