문제

파이썬 단위 테스트가 포함 된 디렉토리가 있습니다. 각 단위 테스트 모듈은 양식입니다 테스트 _*. py. 나는 파일을 만들려고 노력하고있다 all_test.py 그것은 당신이 그것을 추측하고, 위에서 언급 한 테스트 양식에서 모든 파일을 실행하고 결과를 반환 할 것입니다. 나는 지금까지 두 가지 방법을 시도했다. 둘 다 실패했습니다. 나는 두 가지 방법을 보여줄 것이며, 거기에 누군가가 실제로 이것을 정확하게 수행하는 방법을 알고 있기를 바랍니다.

첫 번째 Valiant 시도를 위해 "파일에서 모든 테스트 모듈을 가져 오면 전화를 한 다음 전화를 걸면 unittest.main() Doodad, 그것은 효과가있을 것입니까? "글쎄, 내가 틀렸다는 것이 밝혀졌습니다.

import glob
import unittest

testSuite = unittest.TestSuite()
test_file_strings = glob.glob('test_*.py')
module_strings = [str[0:len(str)-3] for str in test_file_strings]

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

이것은 효과가 없었습니다. 결과는 다음과 같습니다.

$ python all_test.py 

----------------------------------------------------------------------
Ran 0 tests in 0.000s

OK

두 번째 시도를 위해, 나는 아마도, 아마도이 전체 테스트를보다 "매뉴얼"방식으로 수행하려고 노력할 것입니다. 그래서 아래에서 그렇게하려고했습니다.

import glob
import unittest

testSuite = unittest.TestSuite()
test_file_strings = glob.glob('test_*.py')
module_strings = [str[0:len(str)-3] for str in test_file_strings]
[__import__(str) for str in module_strings]
suites = [unittest.TestLoader().loadTestsFromName(str) for str in module_strings]
[testSuite.addTest(suite) for suite in suites]
print testSuite 

result = unittest.TestResult()
testSuite.run(result)
print result

#Ok, at this point I have a result
#How do I display it as the normal unit test command line output?
if __name__ == "__main__":
    unittest.main()

이것은 또한 작동하지 않았지만 너무 가깝게 보입니다!

$ python all_test.py 
<unittest.TestSuite tests=[<unittest.TestSuite tests=[<unittest.TestSuite tests=[<test_main.TestMain testMethod=test_respondes_to_get>]>]>]>
<unittest.TestResult run=1 errors=0 failures=0>

----------------------------------------------------------------------
Ran 0 tests in 0.000s

OK

나는 어떤 종류의 스위트를 가지고있는 것 같고 결과를 실행할 수 있습니다. 나는 그것이 내가 전용이라고 말하는 사실에 대해 조금 걱정하고 있습니다. run=1, 그런 것 같습니다 run=2, 그러나 그것은 진보입니다. 그러나 결과를 메인에 어떻게 전달하고 표시합니까? 아니면 기본적으로 작동하게하려면이 파일을 실행할 수 있도록 어떻게 작동하게하고, 그렇게하면이 디렉토리에서 모든 단위 테스트를 실행합니까?

도움이 되었습니까?

해결책

당신은 당신을 위해 이것을하는 테스트 러너를 사용할 수 있습니다. 예를 들어 아주 좋습니다. 실행되면 현재 트리에서 테스트를 찾아 실행합니다.

업데이트 :

다음은 코 프리 시절의 코드가 있습니다. 당신은 아마도 모듈 이름의 명시적인 목록을 원하지 않지만 나머지는 당신에게 유용 할 것입니다.

testmodules = [
    'cogapp.test_makefiles',
    'cogapp.test_whiteutils',
    'cogapp.test_cogapp',
    ]

suite = unittest.TestSuite()

for t in testmodules:
    try:
        # If the module defines a suite() function, call it to get the suite.
        mod = __import__(t, globals(), locals(), ['suite'])
        suitefn = getattr(mod, 'suite')
        suite.addTest(suitefn())
    except (ImportError, AttributeError):
        # else, just load all the test cases from the module.
        suite.addTest(unittest.defaultTestLoader.loadTestsFromName(t))

unittest.TextTestRunner().run(suite)

다른 팁

Python 2.7 이상을 사용하면 새 코드를 작성하거나 타사 도구를 사용하여이를 수행 할 필요가 없습니다. 명령 줄을 통한 재귀 테스트 실행이 내장되어 있습니다.

python -m unittest discover <test_directory>
# or
python -m unittest discover -s <directory> -p '*_test.py'

당신은 더 많은 것을 읽을 수 있습니다 파이썬 2.7또는 파이썬 3.x UnitTest 문서.

이것은 이제 UnitTest에서 직접 가능합니다. UnitTest.TestLoader.Discover.

import unittest
loader = unittest.TestLoader()
start_dir = 'path/to/your/test/files'
suite = loader.discover(start_dir)

runner = unittest.TextTestRunner()
runner.run(suite)

Python 3에서 사용하는 경우 unittest.TestCase:

  • 빈 (또는 다른 방법)이 있어야합니다. __init__.py 당신의 파일 test 디렉토리 (~ 해야 하다 이름이 지정됩니다 test/)
  • 내부 테스트 파일 test/ 패턴과 일치합니다 test_*.py. 아래 하위 디렉토리 안에있을 수 있습니다 test/, 그리고 그 하위 디어는 무엇이든 이름을 지정할 수 있습니다.

그런 다음 모든 테스트를 다음과 같이 실행할 수 있습니다.

python -m unittest

완료! 100 줄 미만의 솔루션. 다른 파이썬 초보자가 이것을 찾아서 시간을 절약하기를 바랍니다.

비트 위의 코드를 조금 연구함으로써 (특히 사용 TextTestRunner 그리고 defaultTestLoader), 나는 꽤 가까워 질 수 있었다. 결국 나는 모든 테스트 스위트를 단일 스위트 생성자에게 전달하여 코드를 "수동으로"추가하지 않고 코드를 수정하여 다른 문제를 해결했습니다. 그래서 여기 내 해결책이 있습니다.

import glob
import unittest

test_files = glob.glob('test_*.py')
module_strings = [test_file[0:len(test_file)-3] for test_file in test_files]
suites = [unittest.defaultTestLoader.loadTestsFromName(test_file) for test_file in module_strings]
test_suite = unittest.TestSuite(suites)
test_runner = unittest.TextTestRunner().run(test_suite)

예,이 작업보다 코를 사용하는 것이 더 쉽지만 요점 외에는 쉽습니다.

다양한 테스트 케이스 클래스에서 모든 테스트를 실행하려면 명시 적으로 지정하게되어 기쁘다면 다음과 같이 할 수 있습니다.

from unittest import TestLoader, TextTestRunner, TestSuite
from uclid.test.test_symbols import TestSymbols
from uclid.test.test_patterns import TestPatterns

if __name__ == "__main__":

    loader = TestLoader()
    tests = [
        loader.loadTestsFromTestCase(test)
        for test in (TestSymbols, TestPatterns)
    ]
    suite = TestSuite(tests)

    runner = TextTestRunner(verbosity=2)
    runner.run(suite)

어디 uclid 내 프로젝트입니다 TestSymbols 그리고 TestPatterns 서브 클래스입니다 TestCase.

나는 그것을 사용했다 discover 방법 및 과부하 load_tests 이 결과를 얻으려면 (최소한, 내 생각에) 코드의 숫자 줄

def load_tests(loader, tests, pattern):
''' Discover and load all unit tests in all files named ``*_test.py`` in ``./src/``
'''
    suite = TestSuite()
    for all_test_suite in unittest.defaultTestLoader.discover('src', pattern='*_tests.py'):
        for test_suite in all_test_suite:
            suite.addTests(test_suite)
    return suite

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

파이브에 대한 실행

Ran 27 tests in 0.187s
OK

나는 다양한 접근법을 시도했지만 모두 결함이 있거나 코드를 화장해야합니다. 그것은 성가신 것입니다. 그러나 Linux에는 수렴성 방법이 있습니다. 즉, 특정 패턴을 통해 모든 테스트를 찾은 다음 하나씩 호출하는 것입니다.

find . -name 'Test*py' -exec python '{}' \;

그리고 가장 중요한 것은 확실히 작동합니다.

a 포장 라이브러리 또는 응용 프로그램, 당신은 그것을하고 싶지 않습니다. setuptools 당신을 위해 그것을 할 것입니다.

이 명령을 사용하려면 프로젝트의 테스트가 unittest 기능, 테스트 케이스 클래스 또는 방법 또는 모듈 또는 패키지의 테스트 스위트 TestCase 클래스. 명명 된 스위트가 모듈이고 모듈에 additional_tests() 함수, 그것은 호출되고 결과 ( unittest.TestSuite)를 실행할 테스트에 추가됩니다. 명명 된 스위트가 패키지 인 경우 모든 서브 모듈 및 서브 포장지는 전체 테스트 스위트에 재귀 적으로 추가됩니다..

루트 테스트 패키지가 어디에 있는지 알려주십시오.

setup(
    # ...
    test_suite = 'somepkg.test'
)

그리고 달리기 python setup.py test.

파일 기반 발견은 테스트 스위트에서 상대적 수입을 피하지 않는 한 Python 3에서 문제가 될 수 있습니다. discover 파일 가져 오기를 사용합니다. 선택 사항을 지원하더라도 top_level_dir, 그러나 나는 약간의 재귀 오류가있었습니다. 따라서 포장되지 않은 코드에 대한 간단한 솔루션은 다음을 __init__.py 테스트 패키지의 (참조 load_tests 프로토콜).

import unittest

from . import foo, bar


def load_tests(loader, tests, pattern):
    suite = unittest.TestSuite()
    suite.addTests(loader.loadTestsFromModule(foo))
    suite.addTests(loader.loadTestsFromModule(bar))

    return suite

나는 pydev/liclipse를 사용하고 있으며 GUI에서 한 번에 모든 테스트를 한 번에 실행하는 방법을 실제로 찾지 못했습니다. (편집 : 루트 테스트 폴더를 마우스 오른쪽 버튼으로 클릭하고 Run as -> Python unit-test

이것은 내 현재 해결 방법입니다.

import unittest

def load_tests(loader, tests, pattern):
    return loader.discover('.')

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

이 코드를 호출 된 모듈에 넣었습니다 all 내 테스트 디렉토리에서. 이 모듈을 LICLIPSE에서 단위 테스트로 실행하면 모든 테스트가 실행됩니다. 특정 또는 실패한 테스트 만 반복하도록 요청하면 해당 테스트 만 실행됩니다. 내 CommandLine Test Runner를 방해하지 않습니다 (NOSETESTS).

논쟁을 변경해야 할 수도 있습니다 discover 프로젝트 설정을 기반으로합니다.

답을 바탕으로 스티븐 카글 중첩 테스트 모듈에 대한 지원을 추가했습니다.

import fnmatch
import os
import unittest

def all_test_modules(root_dir, pattern):
    test_file_names = all_files_in(root_dir, pattern)
    return [path_to_module(str) for str in test_file_names]

def all_files_in(root_dir, pattern):
    matches = []

    for root, dirnames, filenames in os.walk(root_dir):
        for filename in fnmatch.filter(filenames, pattern):
            matches.append(os.path.join(root, filename))

    return matches

def path_to_module(py_file):
    return strip_leading_dots( \
        replace_slash_by_dot(  \
            strip_extension(py_file)))

def strip_extension(py_file):
    return py_file[0:len(py_file) - len('.py')]

def replace_slash_by_dot(str):
    return str.replace('\\', '.').replace('/', '.')

def strip_leading_dots(str):
    while str.startswith('.'):
       str = str[1:len(str)]
    return str

module_names = all_test_modules('.', '*Tests.py')
suites = [unittest.defaultTestLoader.loadTestsFromName(mname) for mname 
    in module_names]

testSuite = unittest.TestSuite(suites)
runner = unittest.TextTestRunner(verbosity=1)
runner.run(testSuite)

코드는 모든 하위 디렉터를 검색합니다 . ~을 위한 *Tests.py 그런 다음로드 된 파일. 각각을 기대합니다 *Tests.py 단일 클래스를 포함합니다 *Tests(unittest.TestCase) 차례로로드되고 차례로 실행됩니다.

이것은 디렉토리/모듈의 임의의 깊은 둥지와 함께 작동하지만 그 사이의 각 디렉토리는 빈 공간을 포함해야합니다. __init__.py 적어도 파일. 이를 통해 테스트는 슬래시 (또는 백 슬래시)를 도트로 교체하여 중첩 모듈을로드 할 수 있습니다 (참조 replace_slash_by_dot).

테스트 발견은 완전한 주제 인 것처럼 보이기 때문에 발견을 테스트 할 전용 프레임 워크가 있습니다.

더 많은 독서 : https://wiki.python.org/moin/pythontestingToolstaxonomy

이 bash 스크립트는 파일 시스템의 어느 곳에서나 파일 테스트 테스트 디렉토리를 실행합니다. test 디렉토리가 있습니다.

모든 테스트, 독립 $ pwd

UnitTest Python 모듈은 현재 디렉토리에 민감합니다. discover -s 옵션).

이것은 머무를 때 유용합니다 ./src 또는 ./example 작업 디렉토리와 빠른 전반적인 단위 테스트가 필요합니다.

#!/bin/bash
this_program="$0"
dirname="`dirname $this_program`"
readlink="`readlink -e $dirname`"

python -m unittest discover -s "$readlink"/test -v

선택된 테스트, 독립 $ PWD

이 유틸리티 파일의 이름을 지정합니다. runone.py 다음과 같이 사용하십시오.

runone.py <test-python-filename-minus-dot-py-fileextension>
#!/bin/bash
this_program="$0"
dirname="`dirname $this_program`"
readlink="`readlink -e $dirname`"

(cd "$dirname"/test; python -m unittest $1)

필요 없어 test/__init__.py 제작 중에 패키지/메모리 오버 헤드에 부담을주는 파일.

다음은 제작을 통해 내 접근 방식입니다 포장지 명령 줄에서 테스트를 실행하려면 :

#!/usr/bin/env python3
import os, sys, unittest, argparse, inspect, logging

if __name__ == '__main__':
    # Parse arguments.
    parser = argparse.ArgumentParser(add_help=False)
    parser.add_argument("-?", "--help",     action="help",                        help="show this help message and exit" )
    parser.add_argument("-v", "--verbose",  action="store_true", dest="verbose",  help="increase output verbosity" )
    parser.add_argument("-d", "--debug",    action="store_true", dest="debug",    help="show debug messages" )
    parser.add_argument("-h", "--host",     action="store",      dest="host",     help="Destination host" )
    parser.add_argument("-b", "--browser",  action="store",      dest="browser",  help="Browser driver.", choices=["Firefox", "Chrome", "IE", "Opera", "PhantomJS"] )
    parser.add_argument("-r", "--reports-dir", action="store",   dest="dir",      help="Directory to save screenshots.", default="reports")
    parser.add_argument('files', nargs='*')
    args = parser.parse_args()

    # Load files from the arguments.
    for filename in args.files:
        exec(open(filename).read())

    # See: http://codereview.stackexchange.com/q/88655/15346
    def make_suite(tc_class):
        testloader = unittest.TestLoader()
        testnames = testloader.getTestCaseNames(tc_class)
        suite = unittest.TestSuite()
        for name in testnames:
            suite.addTest(tc_class(name, cargs=args))
        return suite

    # Add all tests.
    alltests = unittest.TestSuite()
    for name, obj in inspect.getmembers(sys.modules[__name__]):
        if inspect.isclass(obj) and name.startswith("FooTest"):
            alltests.addTest(make_suite(obj))

    # Set-up logger
    verbose = bool(os.environ.get('VERBOSE', args.verbose))
    debug   = bool(os.environ.get('DEBUG', args.debug))
    if verbose or debug:
        logging.basicConfig( stream=sys.stdout )
        root = logging.getLogger()
        root.setLevel(logging.INFO if verbose else logging.DEBUG)
        ch = logging.StreamHandler(sys.stdout)
        ch.setLevel(logging.INFO if verbose else logging.DEBUG)
        ch.setFormatter(logging.Formatter('%(asctime)s %(levelname)s: %(name)s: %(message)s'))
        root.addHandler(ch)
    else:
        logging.basicConfig(stream=sys.stderr)

    # Run tests.
    result = unittest.TextTestRunner(verbosity=2).run(alltests)
    sys.exit(not result.wasSuccessful())

단순성을 위해서, 내 비 변명pep8 코딩 표준.

그런 다음 모든 테스트에 대한 일반적인 구성 요소에 대한베이스 테스트 클래스를 만들 수 있으므로 각 테스트 각각은 다음과 같습니다.

from BaseTest import BaseTest
class FooTestPagesBasic(BaseTest):
    def test_foo(self):
        driver = self.driver
        driver.get(self.base_url + "/")

실행하려면 단순히 명령 줄 인수의 일부로 테스트를 지정합니다.

./run_tests.py -h http://example.com/ tests/**/*.py
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top