라이브러리 또는 앱을 작성하는 경우 단위 테스트 파일은 어디에 있습니까?
테스트 파일을 기본 앱 코드와 분리하는 것이 좋지만 테스트 할 모듈을 가져 오기가 더 어려워 앱 루트 디렉토리 내부의 "tests"서브 디렉토리에 파일을 저장하는 것이 어색합니다.
모범 사례가 있습니까?
라이브러리 또는 앱을 작성하는 경우 단위 테스트 파일은 어디에 있습니까?
테스트 파일을 기본 앱 코드와 분리하는 것이 좋지만 테스트 할 모듈을 가져 오기가 더 어려워 앱 루트 디렉토리 내부의 "tests"서브 디렉토리에 파일을 저장하는 것이 어색합니다.
모범 사례가 있습니까?
답변:
파일의 module.py
경우, 단위 테스트는 일반적으로 test_module.py
Pythonic 명명 규칙에 따라 호출되어야합니다 .
다음과 같이 일반적으로 허용되는 몇 가지 장소가 있습니다 test_module.py
.
module.py
.../tests/test_module.py
(코드 디렉토리와 같은 수준에서).tests/test_module.py
(코드 디렉토리 아래 한 수준).테스트를 찾아서 가져 오는 것이 간단하다는 점에서 # 1을 선호합니다. 사용중인 빌드 시스템이 무엇이든로 시작하는 파일을 실행하도록 쉽게 구성 할 수 있습니다 test_
. 실제로 테스트 검색에 사용되는 기본 unittest
패턴은test*.py
입니다.
테스트 파일이 하나 뿐인 경우 최상위 디렉토리에 배치하는 것이 좋습니다.
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__.py
에 tests/
폴더
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
일반적인 방법은 tests 디렉토리를 모듈 / 패키지와 동일한 상위 디렉토리에 두는 것입니다. 따라서 모듈의 이름이 foo.py 인 경우 디렉토리 레이아웃은 다음과 같습니다.
parent_dir/
foo.py
tests/
물론 할 수있는 방법은 없습니다. tests 하위 디렉토리를 만들고 absolute import를 사용하여 모듈을 가져올 수도 있습니다.
테스트를하는 곳마다 코 를 사용하여 테스트하는 것이 좋습니다 . 코는 디렉토리에서 테스트를 위해 검색합니다. 이런 방식으로 조직에서 가장 의미있는 곳에 테스트를 배치 할 수 있습니다.
Python 프로그램에 대한 단위 테스트를 생성하는 Pythoscope ( https://pypi.org/project/pythoscope/ )를 작성할 때도 같은 질문이있었습니다 . 우리는 디렉토리를 선택하기 전에 파이썬 목록에서 테스트하는 사람들을 설문 조사했습니다. 여러 가지 의견이있었습니다. 결국 우리는 "tests"디렉토리를 소스 코드와 같은 디렉토리에두기로 결정했습니다. 해당 디렉토리에서 상위 디렉토리의 각 모듈에 대한 테스트 파일을 생성합니다.
나는 또한 제레미 캔 트렐 (Jeremy Cantrell)이 노트에서 언급했듯이 단위 테스트를 파일 자체에 넣는 경향이 있지만, 테스트 기능을 본체에 넣지 않고 오히려 모든 것을
if __name__ == '__main__':
do tests...
블록. 결과적으로 테스트중인 파이썬 파일을 사용하는 방법에 대한 문서를 '예제 코드'로 파일에 추가합니다.
추가해야합니다. 매우 엄격한 모듈 / 클래스를 작성하는 경향이 있습니다. 모듈에 매우 많은 수의 테스트가 필요한 경우 다른 테스트에 넣을 수 있지만 여전히 추가 할 수 있습니다.
if __name__ == '__main__':
import tests.thisModule
tests.thisModule.runtests
이를 통해 소스 코드를 읽는 사람은 누구나 테스트 코드를 찾을 위치를 알 수 있습니다.
때때로 나는 테스트 배치의 주제를 체크 아웃하고 대다수가 라이브러리 코드 옆에 별도의 폴더 구조를 추천 할 때마다 인수가 같고 설득력이 없다는 것을 알았습니다. 테스트 모듈을 핵심 모듈 옆에 놓았습니다.
이를 수행하는 주된 이유는 리팩토링 입니다.
내가 물건을 움직일 때 테스트 모듈이 코드와 함께 움직이기를 원합니다. 별도의 트리에 있으면 테스트를 잃기 쉽습니다. 솔직히 말하면 django , flask 및 다른 많은 폴더와 같이 완전히 다른 폴더 구조로 끝납니다 . 신경 쓰지 않으면 괜찮습니다.
스스로에게 물어보아야 할 주요 질문은 다음과 같습니다.
내가 쓰고 있니?
만약:
별도의 폴더와 그 구조를 유지하기위한 추가 노력이 더 적합 할 수 있습니다. 테스트 에 프로덕션 환경에 배포되는 것에 대해 아무도 불평하지 않습니다 .
그러나 테스트가 핵심 폴더와 혼합 될 때 배포되는 것을 제외하는 것도 쉽습니다. 이것을 setup.py에 넣으십시오 :
find_packages("src", exclude=["*.tests", "*.tests.*", "tests.*", "tests"])
b 인 경우 :
우리 모두가하는 것처럼 재사용 가능한 라이브러리를 작성하기를 원하지만 대부분의 시간은 프로젝트의 수명과 관련이 있습니다. 프로젝트를 쉽게 관리 할 수있는 능력이 우선 순위가되어야합니다.
그런 다음 잘 수행하고 모듈이 다른 프로젝트에 적합하면 분기되거나 별도의 라이브러리로 작성되지 않고이 새 프로젝트로 복사되고 동일한 폴더 구조에서 옆에있는 테스트를 이동합니다. 별도의 테스트 폴더가 된 엉망으로 테스트를 마무리하는 것에 비해 쉽습니다. (처음에는 엉망이되어서는 안되지만 여기서 현실화 하자고 주장 할 수 있습니다).
따라서 선택은 여전히 당신의 선택이지만 혼합 테스트를 통해 별도의 폴더와 동일한 모든 것을 달성하지만 깔끔하게 유지하는 노력이 적습니다.
나는 "모범 사례"가 확립되어 있다고 생각하지 않습니다.
테스트를 앱 코드 외부의 다른 디렉토리에 넣었습니다. 그런 다음 모든 테스트를 실행하기 전에 기본 응용 프로그램 디렉토리를 sys.path에 추가하여 테스트 실행기 스크립트 (다른 작업도 수행)에서 모듈을 가져올 수 있습니다. 이 방법으로 테스트 코드를 릴리스 할 때 기본 디렉토리에서 테스트 디렉토리를 제거 할 필요가 없으므로 시간과 노력을 절약 할 수 있습니다.
os.sys.path.append(os.dirname('..'))
파이썬에서 테스팅 프레임 워크를 개발 한 경험에서 파이썬 단위 테스트를 별도의 디렉토리에 두는 것이 좋습니다. 대칭 디렉토리 구조를 유지하십시오. 이는 핵심 라이브러리 만 패키징하고 단위 테스트를 패키징하는 데 도움이됩니다. 아래는 회로도를 통해 구현됩니다.
<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을 사용하여 이러한 라이브러리를 패키징 할 때 주 라이브러리 모듈 만 패키징 할 수 있습니다. 이는 특히 민첩한 환경에서 유지 관리 성을 돕습니다.
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 확인
matplotlib
아래에있다 matplotlib/lib/matplotlib/tests
( github.com/matplotlib/matplotlib/tree/... ) sklearn
아래에있다 scikitelearn/sklearn/tests
( github.com/scikit-learn/scikit-learn/tree/master/sklearn/tests )
내가 어떻게 ...
폴더 구조 :
project/
src/
code.py
tests/
setup.py
Setup.py는 내 프로젝트 모듈을 포함하는 위치로 src /를 가리킨 다음 다음을 실행합니다.
setup.py develop
프로젝트를 사이트 패키지에 추가하여 작업 사본을 가리 킵니다. 내 테스트를 실행하려면 다음을 사용하십시오.
setup.py tests
내가 구성한 테스트 러너를 사용하십시오.
code.py
. 최상위 디렉토리 "프로젝트"를 호출하는 것이 더 합리적입니다.
최상위 테스트 디렉토리를 선호합니다. 이것은 수입이 조금 더 어려워진다는 것을 의미합니다. 이를 위해 두 가지 해결책이 있습니다.
test_suite='tests.runalltests.suite'
로setup()
간단하게 테스트를 실행할 수 있습니다.python setup.py test
PYTHONPATH=. python tests/runalltests.py
M2Crypto의 코드에서 그 기능을 지원하는 방법은 다음과 같습니다.
nosetest로 테스트를 실행하려면 약간 다른 작업이 필요할 수 있습니다.
테스트가 간단하다면 간단히 docstring에 넣습니다. Python의 대부분의 테스트 프레임 워크는 다음을 사용할 수 있습니다.
>>> import module
>>> module.method('test')
'testresult'
다른 관련 테스트의 경우 ../tests/test_module.py
또는에 넣습니다 tests/test_module.py
.
"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"를 사용할 수 있습니다. 특정 제품군입니다.
테스트중인 코드 (CUT)와 동일한 디렉토리에 테스트를 넣었습니다. 에 대한 foo.py
시험에있을 것 foo_ut.py
또는 유사한. (이를 찾기 위해 테스트 검색 프로세스를 조정했습니다.)
이렇게하면 코드 옆에 테스트가 디렉토리 목록에 표시되어 테스트가 있음을 분명히하고 별도의 파일에있을 때 가능한 한 쉽게 테스트를 열 수 있습니다. (명령 행 편집기의 vim foo*
경우 그래픽 파일 시스템 브라우저를 사용하는 경우 CUT 파일을 클릭 한 다음 바로 인접한 테스트 파일을 클릭하십시오.)
다른 사람들이 지적했듯이 , 이것은 필요할 때 다른 곳에서 사용하기 위해 코드를 리팩토링하고 추출하는 것을 더 쉽게 만듭니다.
테스트를 완전히 다른 디렉토리 트리에 넣는 아이디어는 정말 마음에 들지 않습니다. CUT을 사용하여 파일을 열 때 개발자가 테스트를 여는 것이 왜 필요한 것보다 어려운가? 대다수의 개발자가 테스트를 작성하거나 조정하는 데 열중하고있는 것은 아니기 때문에 장벽을 변명으로 사용하는 대신 장벽을 무시할 것입니다. (내 경험에서 그 반대입니다. 가능한 한 쉽게 만들더라도 테스트를 작성하는 데 방해가되지 않는 많은 개발자를 알고 있습니다.)