파이썬 단위 테스트는 어디로 가나 요?


490

라이브러리 또는 앱을 작성하는 경우 단위 테스트 파일은 어디에 있습니까?

테스트 파일을 기본 앱 코드와 분리하는 것이 좋지만 테스트 할 모듈을 가져 오기가 더 어려워 앱 루트 디렉토리 내부의 "tests"서브 디렉토리에 파일을 저장하는 것이 어색합니다.

모범 사례가 있습니까?


4
이 질문에 대한 많은 대답이 있으며 Q / A 사이트에 대한 질문이 아닙니다. 사람들은 SO에 관한 모든 유용한 질문을 할 수있는 것은 아닙니다. 전자는 그것을 선택하고 우리는 그들의 규칙을 따라야합니다.
Wouter J

121
또한 사람들은 SO 페이지가 Google 검색에서 가장 인기있는 결과가 될 때 SO 공식 교리를 고수하기보다는 흐름을 따라가는 것이 더 낫다는 것을 이해해야합니다.
Christopher Barber

6
@ChristopherBarber 사람들은 또한 의사 결정과 공격적인 폐쇄가 실제로 더 나은 선택권이 없다면 질문을하지 않을 사이트로서 너무나 유명한 명성을 얻었음을 이해해야합니다.
Stefano Borini

답변:


200

파일의 module.py경우, 단위 테스트는 일반적으로 test_module.pyPythonic 명명 규칙에 따라 호출되어야합니다 .

다음과 같이 일반적으로 허용되는 몇 가지 장소가 있습니다 test_module.py.

  1. 와 같은 디렉토리에 있습니다 module.py.
  2. 에서 ../tests/test_module.py(코드 디렉토리와 같은 수준에서).
  3. 에서 tests/test_module.py(코드 디렉토리 아래 한 수준).

테스트를 찾아서 가져 오는 것이 간단하다는 점에서 # 1을 선호합니다. 사용중인 빌드 시스템이 무엇이든로 시작하는 파일을 실행하도록 쉽게 구성 할 수 있습니다 test_. 실제로 테스트 검색에 사용되는 기본 unittest패턴은test*.py 입니다.


12
load_tests 프로토콜 기본적으로 테스트 *의 평라는 이름의 파일을 검색합니다. 또한, 이 최고 구글 결과이 유닛 테스트 문서는 test_module.py 형식을 사용하는 두.
dfarrell07

6
'test_'로 시작하는 파일이 많지 않으므로 탭 완성을 사용할 때 foo_test.py를 사용하면 키 입력을 저장할 수 있습니다.
juniper-

11
@juniper, 당신의 생각에 따라 module_test는 코딩 할 때 자동 완성에 나타납니다. 혼란 스럽거나 성 가실 수 있습니다.
Medeiros

11
코드를 배포 할 때 프로덕션 위치에 테스트를 배포하고 싶지 않습니다. 따라서 배포 할 때 하나의 디렉토리 './tests/test_blah.py'에 두는 것은 쉬운 일입니다. 또한 일부 테스트는 샘플 데이터 파일을 가져 오므로 테스트 데이터를 배포하지 않으려면 테스트 디렉토리에 파일을 배치해야합니다.
Kevin J. Rice

1
@ KevinJ.Rice 코드가 프로덕션 위치에서 작동하는지 테스트하고 있지 않습니까?
endolith

67

하나의 테스트 파일

테스트 파일이 하나 뿐인 경우 최상위 디렉토리에 배치하는 것이 좋습니다.

module/
    lib/
        __init__.py
        module.py
    test.py

CLI에서 테스트 실행

python test.py

많은 테스트 파일

테스트 파일이 많은 경우 tests폴더에 넣으십시오 .

module/
    lib/
        __init__.py
        module.py
    tests/
        test_module.py
        test_module_function.py
# test_module.py

import unittest
from lib import module

class TestModule(unittest.TestCase):
    def test_module(self):
        pass

if __name__ == '__main__':
    unittest.main()

CLI에서 테스트 실행

# In top-level /module/ folder
python -m tests.test_module
python -m tests.test_module_function

사용하다 unittest discovery

unittest discovery 패키지 폴더에서 모든 테스트를 찾을 수 있습니다.

만들기 __init__.pytests/폴더

module/
    lib/
        __init__.py
        module.py
    tests/
        __init__.py
        test_module.py
        test_module_function.py

CLI에서 테스트 실행

# In top-level /module/ folder

# -s, --start-directory (default current directory)
# -p, --pattern (default test*.py)

python -m unittest discover

참고

단위 테스트 프레임 워크


51

일반적인 방법은 tests 디렉토리를 모듈 / 패키지와 동일한 상위 디렉토리에 두는 것입니다. 따라서 모듈의 이름이 foo.py 인 경우 디렉토리 레이아웃은 다음과 같습니다.

parent_dir/
  foo.py
  tests/

물론 할 수있는 방법은 없습니다. tests 하위 디렉토리를 만들고 absolute import를 사용하여 모듈을 가져올 수도 있습니다.

테스트를하는 곳마다 를 사용하여 테스트하는 것이 좋습니다 . 코는 디렉토리에서 테스트를 위해 검색합니다. 이런 방식으로 조직에서 가장 의미있는 곳에 테스트를 배치 할 수 있습니다.


16
이 작업을 수행하고 싶지만 작동하지 않습니다. 테스트를 실행하려면 parent_dir에 다음을 입력하십시오. "python tests \ foo_test.py"및 foo_test.py : "from ..foo import this that that that the other"오류 : "ValueError : Attempted non-package에서 relative import "parent_dir과 테스트 모두 init .py를 가지고 있으므로 왜 패키지가 아닌지 잘 모르겠습니다. 명령 줄에서 실행하는 최상위 스크립트는 init .py 가있는 디렉토리에 있더라도 패키지의 일부로 간주 될 수 없기 때문 입니다. 테스트는 어떻게합니까? 나는 오늘 Windows에서 일하고 있습니다.면 양말을 축복하십시오.
Jonathan Hartley

4
단위 테스트를 실행하는 가장 좋은 방법은 라이브러리 / 프로그램을 설치 한 다음 코로 단위 테스트를 실행하는 것입니다. 나는 이것을 훨씬 쉽게하기 위해 virtualenv와 virtualenvwrapper를 권장합니다.
Cristian

@Tartley-abtest 가져 오기가 작동하려면 'tests'디렉토리에 init .py 파일 이 필요합니다 . 나는 코 로이 방법을 사용하므로 왜 문제가 있는지 잘 모르겠습니다.
cmcginty 2016 년

4
감사 합니다 Casey-모든 관련 디렉토리에 init .py 파일이 있습니다. 내가 뭘 잘못했는지 모르겠지만 모든 Python 프로젝트 에서이 문제가 발생하여 아무도 다른 사람이없는 이유를 이해할 수 없습니다. 아, 이봐
Jonathan Hartley

8
Python2.6 이상에서 내 문제에 대한 한 가지 해결책은 다음을 사용하여 프로젝트의 루트에서 테스트를 실행하는 것입니다 .python -m project.package.tests.module_tests (python project / package / tests / module_tests.py) . 그러면 테스트 모듈의 디렉토리가 경로에 놓이므로 테스트는 상위 디렉토리로 상대 가져 오기를 수행하여 테스트 대상 모듈을 얻을 수 있습니다.
Jonathan Hartley

32

Python 프로그램에 대한 단위 테스트를 생성하는 Pythoscope ( https://pypi.org/project/pythoscope/ )를 작성할 때도 같은 질문이있었습니다 . 우리는 디렉토리를 선택하기 전에 파이썬 목록에서 테스트하는 사람들을 설문 조사했습니다. 여러 가지 의견이있었습니다. 결국 우리는 "tests"디렉토리를 소스 코드와 같은 디렉토리에두기로 결정했습니다. 해당 디렉토리에서 상위 디렉토리의 각 모듈에 대한 테스트 파일을 생성합니다.


2
대박! 일부 레거시 코드에서 Pythoscope (위대한 로고)를 실행하면 놀라웠습니다. 즉각적인 모범 사례 및 다른 개발자가 실패한 테스트 스텁을 채울 수 있습니다. 이제 대나무에 연결 하시겠습니까? :)
Will

27

나는 또한 제레미 캔 트렐 (Jeremy Cantrell)이 노트에서 언급했듯이 단위 테스트를 파일 자체에 넣는 경향이 있지만, 테스트 기능을 본체에 넣지 않고 오히려 모든 것을

if __name__ == '__main__':
   do tests...

블록. 결과적으로 테스트중인 파이썬 파일을 사용하는 방법에 대한 문서를 '예제 코드'로 파일에 추가합니다.

추가해야합니다. 매우 엄격한 모듈 / 클래스를 작성하는 경향이 있습니다. 모듈에 매우 많은 수의 테스트가 필요한 경우 다른 테스트에 넣을 수 있지만 여전히 추가 할 수 있습니다.

if __name__ == '__main__':
   import tests.thisModule
   tests.thisModule.runtests

이를 통해 소스 코드를 읽는 사람은 누구나 테스트 코드를 찾을 위치를 알 수 있습니다.


"제레미 캔 트렐이 노트 위에"로 어디에?
endolith

나는 이런 방식으로 일하는 것을 좋아한다. 단축키를 사용하여 파일을 실행하도록 가장 간단한 편집기를 구성 할 수 있으므로 코드를 볼 때 즉시 테스트를 실행할 수 있습니다. 불행히도 파이썬 이외의 언어에서는 이것이 끔찍한 것처럼 보일 수 있으므로 C ++ 또는 Java 상점에 있으면 동료가 이것에 눈살을 찌푸 릴 수 있습니다. 또한 코드 범위 도구와 잘 작동하지 않습니다.
Keeely

19

때때로 나는 테스트 배치의 주제를 체크 아웃하고 대다수가 라이브러리 코드 옆에 별도의 폴더 구조를 추천 할 때마다 인수가 같고 설득력이 없다는 것을 알았습니다. 테스트 모듈을 핵심 모듈 옆에 놓았습니다.

이를 수행하는 주된 이유는 리팩토링 입니다.

내가 물건을 움직일 때 테스트 모듈이 코드와 함께 움직이기를 원합니다. 별도의 트리에 있으면 테스트를 잃기 쉽습니다. 솔직히 말하면 django , flask 및 다른 많은 폴더와 같이 완전히 다른 폴더 구조로 끝납니다 . 신경 쓰지 않으면 괜찮습니다.

스스로에게 물어보아야 할 주요 질문은 다음과 같습니다.

내가 쓰고 있니?

  • a) 재사용 가능한 라이브러리 또는
  • b) 반으로 분리 된 모듈을 묶는 것보다 프로젝트를 구축 하는가?

만약:

별도의 폴더와 그 구조를 유지하기위한 추가 노력이 더 적합 할 수 있습니다. 테스트 에 프로덕션 환경에 배포되는 것에 대해 아무도 불평하지 않습니다 .

그러나 테스트가 핵심 폴더와 혼합 될 때 배포되는 것을 제외하는 것도 쉽습니다. 이것을 setup.py에 넣으십시오 :

find_packages("src", exclude=["*.tests", "*.tests.*", "tests.*", "tests"]) 

b 인 경우 :

우리 모두가하는 것처럼 재사용 가능한 라이브러리를 작성하기를 원하지만 대부분의 시간은 프로젝트의 수명과 관련이 있습니다. 프로젝트를 쉽게 관리 할 수있는 능력이 우선 순위가되어야합니다.

그런 다음 잘 수행하고 모듈이 다른 프로젝트에 적합하면 분기되거나 별도의 라이브러리로 작성되지 않고이 새 프로젝트로 복사되고 동일한 폴더 구조에서 옆에있는 테스트를 이동합니다. 별도의 테스트 폴더가 된 엉망으로 테스트를 마무리하는 것에 비해 쉽습니다. (처음에는 엉망이되어서는 안되지만 여기서 현실화 하자고 주장 할 수 있습니다).

따라서 선택은 여전히 ​​당신의 선택이지만 혼합 테스트를 통해 별도의 폴더와 동일한 모든 것을 달성하지만 깔끔하게 유지하는 노력이 적습니다.


1
실제로 테스트를 프로덕션에 배포하는 데 어떤 문제가 있습니까? 내 경험에 따르면 매우 유용합니다. 사용자가 실제로 환경에서 테스트를 실행할 수 있도록 허용합니다 ... 버그 보고서를받을 때 사용자에게 테스트 스위트를 실행하여 모든 것이 올바르게 있는지 확인하고 테스트를위한 핫 패치를 보내도록 요청할 수 있습니다. 당신이 것을 module.tests에서 테스트를 넣어 때문에 스위트 직접 ... 게다가, 그것은 아니에요 것이다 당신은 당신의 설정 파일에 뭔가 잘못했다하지 않는 한, 생산에 결국 ...
anarcat

2
내 답변에 썼 듯이 일반적으로 테스트를 분리하지 않습니다. 그러나. 배포 패키지에 테스트를 넣으면 일반적으로 프로덕션 환경에서 원하지 않는 것들 (예 : 일부 모듈 레벨 코드)이 실행될 수 있습니다. 물론 테스트 작성 방법에 따라 달라 지지만, 안전을 위해 테스트를 중단하면 아무도 실수로 유해한 것을 실행하지 않습니다. 배포판에 테스트를 포함시키는 것에 반대하지는 않지만 경험상 일반적으로 안전하다는 것을 이해합니다. 그리고 별도의 폴더에 넣으면 dist에 포함시키지 않는 것이 매우 쉽습니다.
Janusz Skonieczny

15

내가 사용하는 tests/디렉토리를하고 상대의 수입을 사용하여 주 응용 프로그램 모듈을 가져옵니다. 따라서 MyApp / tests / foo.py에는 다음이있을 수 있습니다.

from .. import foo

MyApp.foo모듈 을 가져옵니다 .


5
"ValueError : 패키지 이외의 상대 가져 오기를 시도했습니다"
cprn

12

나는 "모범 사례"가 확립되어 있다고 생각하지 않습니다.

테스트를 앱 코드 외부의 다른 디렉토리에 넣었습니다. 그런 다음 모든 테스트를 실행하기 전에 기본 응용 프로그램 디렉토리를 sys.path에 추가하여 테스트 실행기 스크립트 (다른 ​​작업도 수행)에서 모듈을 가져올 수 있습니다. 이 방법으로 테스트 코드를 릴리스 할 때 기본 디렉토리에서 테스트 디렉토리를 제거 할 필요가 없으므로 시간과 노력을 절약 할 수 있습니다.


3
그런 다음 기본 응용 프로그램 디렉토리를 sys.path에 추가합니다 . 문제는 테스트에 테스트 웹 서버와 같은 일부 도우미 모듈이 포함되어 있고 적절한 테스트 내에서 이러한 도우미 모듈을 가져와야하는 경우입니다.
Piotr Dobrogost

이것은 나를 위해 다음과 같이 보입니다 :os.sys.path.append(os.dirname('..'))
Matt M.

11

파이썬에서 테스팅 프레임 워크를 개발 한 경험에서 파이썬 단위 테스트를 별도의 디렉토리에 두는 것이 좋습니다. 대칭 디렉토리 구조를 유지하십시오. 이는 핵심 라이브러리 만 패키징하고 단위 테스트를 패키징하는 데 도움이됩니다. 아래는 회로도를 통해 구현됩니다.

                              <Main Package>
                               /          \
                              /            \
                            lib           tests
                            /                \
             [module1.py, module2.py,  [ut_module1.py, ut_module2.py,
              module3.py  module4.py,   ut_module3.py, ut_module.py]
              __init__.py]

이런 식으로 rpm을 사용하여 이러한 라이브러리를 패키징 할 때 주 라이브러리 모듈 만 패키징 할 수 있습니다. 이는 특히 민첩한 환경에서 유지 관리 성을 돕습니다.


1
이 접근 방식의 잠재적 인 장점 중 하나는 테스트를 독자적인 응용 프로그램으로 개발할 수 있다는 것입니다. 물론 모든 이점에는 단점이 있습니다. 대칭을 유지하는 것은 기본적으로 "이중 항목 계산"을 수행하고 리팩토링을 더 성가 시게합니다.
Jasha

소프트 후속 질문 : 애자일 환경이 특히이 접근 방식에 적합한 이유는 무엇입니까? (즉, 민첩한 워크 플로우는 대칭 디렉토리 구조를 매우 유용하게 만드는가?)
Jasha

11

GitHub에서 주요 Python 프로젝트를 확인하고 아이디어를 얻는 것이 좋습니다.

코드가 커지고 라이브러리를 더 추가 할 때 setup.py와 동일한 디렉토리에 테스트 폴더를 작성하고 각 테스트 유형 (단위 테스트, 통합 등)에 대한 프로젝트 디렉토리 구조를 미러링하는 것이 좋습니다.

예를 들어 다음과 같은 디렉토리 구조가있는 경우

myPackage/
    myapp/
       moduleA/
          __init__.py
          module_A.py
       moduleB/
          __init__.py
          module_B.py
setup.py

테스트 폴더를 추가하면 다음과 같은 디렉토리 구조가 생깁니다.

myPackage/
    myapp/
       moduleA/
          __init__.py
          module_A.py
       moduleB/
          __init__.py
          module_B.py
test/
   unit/
      myapp/
         moduleA/
            module_A_test.py
         moduleB/
            module_B_test.py
   integration/
          myapp/
             moduleA/
                module_A_test.py
             moduleB/
                module_B_test.py
setup.py

올바르게 작성된 많은 Python 패키지는 동일한 구조를 사용합니다. 아주 좋은 예는 Boto 패키지입니다. https://github.com/boto/boto 확인


1
"test"는 모듈의 Python 빌드이므로 "test"대신 "tests"를 사용하는 것이 좋습니다. docs.python.org/2/library/test.html
brodul

항상 .. 예를 들어 matplotlib아래에있다 matplotlib/lib/matplotlib/tests( github.com/matplotlib/matplotlib/tree/... ) sklearn아래에있다 scikitelearn/sklearn/tests( github.com/scikit-learn/scikit-learn/tree/master/sklearn/tests )
alpha_989

7

내가 어떻게 ...

폴더 구조 :

project/
    src/
        code.py
    tests/
    setup.py

Setup.py는 내 프로젝트 모듈을 포함하는 위치로 src /를 가리킨 다음 다음을 실행합니다.

setup.py develop

프로젝트를 사이트 패키지에 추가하여 작업 사본을 가리 킵니다. 내 테스트를 실행하려면 다음을 사용하십시오.

setup.py tests

내가 구성한 테스트 러너를 사용하십시오.


"모듈"이라는 용어를 재정의 한 것 같습니다. 대부분의 파이썬 프로그래머는 아마도 모듈이 당신이 호출 한 파일이라고 생각할 것입니다 code.py. 최상위 디렉토리 "프로젝트"를 호출하는 것이 더 합리적입니다.
blokeley

4

최상위 테스트 디렉토리를 선호합니다. 이것은 수입이 조금 더 어려워진다는 것을 의미합니다. 이를 위해 두 가지 해결책이 있습니다.

  1. setuptools를 사용하십시오. 그럼 당신은 통과 할 수 test_suite='tests.runalltests.suite'setup() 간단하게 테스트를 실행할 수 있습니다.python setup.py test
  2. 테스트를 실행할 때 PYTHONPATH를 설정하십시오. PYTHONPATH=. python tests/runalltests.py

M2Crypto의 코드에서 그 기능을 지원하는 방법은 다음과 같습니다.

nosetest로 테스트를 실행하려면 약간 다른 작업이 필요할 수 있습니다.


3

우리는 사용

app/src/code.py
app/testing/code_test.py 
app/docs/..

각 테스트 파일에서 우리는 삽입 ../src/에서 sys.path. 가장 좋은 해결책은 아니지만 작동합니다. 누군가가 자바에서 maven과 같은 것을 사용하면 어떤 프로젝트를 수행하든 작동하는 표준 규칙을 제공하는 것이 좋을 것이라고 생각합니다.


1

테스트가 간단하다면 간단히 docstring에 넣습니다. Python의 대부분의 테스트 프레임 워크는 다음을 사용할 수 있습니다.

>>> import module
>>> module.method('test')
'testresult'

다른 관련 테스트의 경우 ../tests/test_module.py또는에 넣습니다 tests/test_module.py.


1

C #에서는 일반적으로 테스트를 별도의 어셈블리로 분리했습니다.

파이썬에서-지금까지는 테스트가 함수의 docstring에있는 doctest를 작성하거나 if __name__ == "__main__"모듈 하단의 블록에 넣는 경향이있었습니다 .


0

"foo"라는 패키지를 작성할 때 단위 테스트를 별도의 패키지 "foo_test"에 넣습니다. 그러면 모듈 및 하위 패키지는 SUT 패키지 모듈과 이름이 동일합니다. 예를 들어 foo.xy 모듈에 대한 테스트는 foo_test.xy에 있습니다. 각 테스트 패키지의 __init__.py 파일은 패키지의 모든 테스트 스위트를 포함하는 AllTests 스위트를 포함합니다. setuptools는 기본 테스트 패키지를 지정하는 편리한 방법을 제공하므로 "python setup.py develop"후에 "python setup.py test"또는 "python setup.py test -s foo_test.x.SomeTestSuite"를 사용할 수 있습니다. 특정 제품군입니다.


0

테스트중인 코드 (CUT)와 동일한 디렉토리에 테스트를 넣었습니다. 에 대한 foo.py시험에있을 것 foo_ut.py또는 유사한. (이를 찾기 위해 테스트 검색 프로세스를 조정했습니다.)

이렇게하면 코드 옆에 테스트가 디렉토리 목록에 표시되어 테스트가 있음을 분명히하고 별도의 파일에있을 때 가능한 한 쉽게 테스트를 열 수 있습니다. (명령 행 편집기의 vim foo*경우 그래픽 파일 시스템 브라우저를 사용하는 경우 CUT 파일을 클릭 한 다음 바로 인접한 테스트 파일을 클릭하십시오.)

다른 사람들이 지적했듯이 , 이것은 필요할 때 다른 곳에서 사용하기 위해 코드를 리팩토링하고 추출하는 것을 더 쉽게 만듭니다.

테스트를 완전히 다른 디렉토리 트리에 넣는 아이디어는 정말 마음에 들지 않습니다. CUT을 사용하여 파일을 열 때 개발자가 테스트를 여는 것이 왜 필요한 것보다 어려운가? 대다수의 개발자가 테스트를 작성하거나 조정하는 데 열중하고있는 것은 아니기 때문에 장벽을 변명으로 사용하는 대신 장벽을 무시할 것입니다. (내 경험에서 그 반대입니다. 가능한 한 쉽게 만들더라도 테스트를 작성하는 데 방해가되지 않는 많은 개발자를 알고 있습니다.)


-2

최근에 파이썬으로 프로그래밍을 시작했기 때문에 아직 모범 사례를 찾을 기회가 없었습니다. 그러나 모든 테스트를 찾아서 실행하는 모듈을 작성했습니다.

그래서 나는 가지고있다:

앱/
 appfile.py
테스트/
 appfileTest.py

더 큰 프로젝트로 진행하면서 어떻게 진행되는지 확인해야합니다.


4
안녕하세요, 낙타 케이스는 파이썬 세계에서 조금 이상합니다.
스튜어트 Axon
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.