명령 줄을 통해 unittest.TestCase에서 단일 테스트 실행


256

우리 팀에서는 다음과 같이 대부분의 테스트 사례를 정의합니다.

하나의 "프레임 워크"클래스 ourtcfw.py:

import unittest

class OurTcFw(unittest.TestCase):
    def setUp:
        # something

    # other stuff that we want to use everywhere

testMyCase.py와 같은 많은 테스트 사례 :

import localweather

class MyCase(OurTcFw):

    def testItIsSunny(self):
        self.assertTrue(localweather.sunny)

    def testItIsHot(self):
        self.assertTrue(localweather.temperature > 20)

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

새 테스트 코드를 작성하고 자주 실행하고 시간을 절약하고 싶을 때 다른 모든 테스트 앞에 "__"을 두는 것입니다. 그러나 번거롭고 작성중인 코드에서 산만 해지 며 커밋 노이즈가 생기면 성가신 일입니다.

예를 들어로 변경하면 다음 testItIsHot()과 같이 할 수 있기를 원합니다.

$ python testMyCase.py testItIsHot

그리고 한 unittest실행 testItIsHot()

어떻게하면 되나요?

나는 if __name__ == "__main__":부분 을 다시 쓰려고 노력했지만 파이썬을 처음 접했기 때문에 길을 잃어 버리고 메서드 이외의 모든 것에 부딪 히고 있습니다.

답변:


311

이것은 제안한대로 작동합니다. 클래스 이름도 지정해야합니다.

python testMyCase.py MyCase.testItIsHot

2
어머! 테스트는 python2.6 (python2.7로 테스트 자체를 테스트 할 수 있는 시간의 99 %)에서 실행되기 때문에 2.6.8 doc을보고 너무 많이보고 싶었습니다! :-)
Alois Mahdal

1
이 방법은 "test *"라고 불리는 경우에만 작동하므로 불행히도 이름을 변경하여 "비활성화 된"테스트를 실행할 수 없습니다.
Alois Mahdal

4
성숙한 파이썬 프로그램에서 가장 일반적인 경우 인 하위 디렉토리에서 테스트를 수행 할 수 없습니다.
Tom Swirly

4
@TomSwirly 지금 확인할 수는 없지만 __init__.py그 끔찍한 내부 (및 하위 디렉토리가있는 경우)를 작성하고 (예 : 하위 디렉토리) 호출하면 가능합니다. python test/testMyCase.py test.MyCase.testItIsHot.
Alois Mahdal

1
이 작업을 수행해도 아무 변화가 없습니다. 해결 방법을 찾았지만이 방법이 효과가 있기를 바랍니다.
Joe Flack

152

테스트 케이스를 구성하는 경우, 즉 실제 코드와 같은 동일한 조직을 따르고 동일한 패키지의 모듈에 대해 상대적 가져 오기를 사용하십시오.

다음 명령 형식을 사용할 수도 있습니다.

python -m unittest mypkg.tests.test_module.TestClass.test_method
# In your case, this would be:
python -m unittest testMyCase.MyCase.testItIsHot

이에 대한 Python3 설명서 : https://docs.python.org/3/library/unittest.html#command-line-interface


이것은 엄청나게 Java에 해당합니다. "long_module_name.SameLongNameAsAClass.test_long_name_beginning_with_test_as_a_convention"... 더 나은 코드를 테스트하는 제정신이 아닌 사람처럼 제품군으로 모듈화하지 않았기를 바랍니다.
Joshua Detwiler

69

추측 한대로 잘 작동 할 수 있습니다

python testMyCase.py MyCase.testItIsHot

그리고 테스트하는 또 다른 방법이 있습니다 testItIsHot.

    suite = unittest.TestSuite()
    suite.addTest(MyCase("testItIsHot"))
    runner = unittest.TextTestRunner()
    runner.run(suite)

11
이 답변의 두 번째 부분이 매우 유용하다는 것을 알았습니다 .Eclipse + PyDev에서 테스트를 작성 중이며 명령 줄로 전환하고 싶지 않습니다!
Giovanni Di Milia

25

unittest 모듈의 도움말을 확인하면 모듈에서 테스트 케이스 클래스를 실행하고 테스트 케이스 클래스에서 테스트 메소드를 실행할 수있는 몇 가지 조합에 대해 알려줍니다.

python3 -m unittest -h

[...]

Examples:
  python3 -m unittest test_module               - run tests from test_module
  python3 -m unittest module.TestClass          - run tests from module.TestClass
  python3 -m unittest module.Class.test_method  - run specified test method

unittest.main()모듈의 기본 동작으로 a를 정의 할 필요는 없습니다 .


2
+1과 용어부터 언어에 새로운 경우 혼동 (그리고이 될 수 usage도 이상한 일관성) : 실행이 python -m unittest module_test.TestClass.test_method파일 가정 module_test.py(현재 디렉토리에서 실행을 그리고 __init.py__있다 되지 필수); 그리고 module_test.py포함 class TestClass(unittest.TestCase)...하는 내용 def test_method(self,...)(파이썬 2.7.13에서도 작동합니다)
michael

10

아마도 누군가에게 도움이 될 것입니다. 특정 클래스의 테스트 만 실행하려는 경우 :

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

파이썬 3.6에서 작동합니다.


3

@yarkee에서 영감을 얻어 이미 얻은 코드 중 일부와 결합했습니다. run_unit_tests()명령 줄을 사용하지 않고 함수 를 호출하거나 다른 명령을 사용하여 다른 스크립트에서이를 호출 할 수도 있습니다 python3 my_test_file.py.

import my_test_file
my_test_file.run_unit_tests()

슬프게도 이것은 Python 3.3우수하거나 우수합니다.

import unittest

class LineBalancingUnitTests(unittest.TestCase):

    @classmethod
    def setUp(self):
        self.maxDiff = None

    def test_it_is_sunny(self):
        self.assertTrue("a" == "a")

    def test_it_is_hot(self):
        self.assertTrue("a" != "b")

러너 코드 :

#! /usr/bin/env python3
# -*- coding: utf-8 -*-
import unittest
from .somewhere import LineBalancingUnitTests

def create_suite(classes, unit_tests_to_run):
    suite = unittest.TestSuite()
    unit_tests_to_run_count = len( unit_tests_to_run )

    for _class in classes:
        _object = _class()
        for function_name in dir( _object ):
            if function_name.lower().startswith( "test" ):
                if unit_tests_to_run_count > 0 \
                        and function_name not in unit_tests_to_run:
                    continue
                suite.addTest( _class( function_name ) )
    return suite

def run_unit_tests():
    runner = unittest.TextTestRunner()
    classes =  [
        LineBalancingUnitTests,
    ]

    # Comment all the tests names on this list, to run all Unit Tests
    unit_tests_to_run =  [
        "test_it_is_sunny",
        # "test_it_is_hot",
    ]
    runner.run( create_suite( classes, unit_tests_to_run ) )

if __name__ == "__main__":
    print( "\n\n" )
    run_unit_tests()

코드를 약간 편집하면 호출하려는 모든 단위 테스트로 배열을 전달할 수 있습니다.

...
def run_unit_tests(unit_tests_to_run):
    runner = unittest.TextTestRunner()

    classes = \
    [
        LineBalancingUnitTests,
    ]

    runner.run( suite( classes, unit_tests_to_run ) )
...

그리고 다른 파일 :

import my_test_file

# Comment all the tests names on this list, to run all Unit Tests
unit_tests_to_run = \
[
    "test_it_is_sunny",
    # "test_it_is_hot",
]

my_test_file.run_unit_tests( unit_tests_to_run )

또는 https://docs.python.org/3/library/unittest.html#load-tests-protocol 을 사용하고 테스트 모듈 / 파일에서 다음 방법을 정의 할 수 있습니다 .

def load_tests(loader, standard_tests, pattern):
    suite = unittest.TestSuite()

    # To add a single test from this file
    suite.addTest( LineBalancingUnitTests( 'test_it_is_sunny' ) )

    # To add a single test class from this file
    suite.addTests( unittest.TestLoader().loadTestsFromTestCase( LineBalancingUnitTests ) )

    return suite

실행을 하나의 단일 테스트 파일로 제한하려면 테스트 검색 패턴을 load_tests()함수 를 정의한 유일한 파일로 설정하면됩니다 .

#! /usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import sys
import unittest

test_pattern = 'mytest/module/name.py'
PACKAGE_ROOT_DIRECTORY = os.path.dirname( os.path.realpath( __file__ ) )

loader = unittest.TestLoader()
start_dir = os.path.join( PACKAGE_ROOT_DIRECTORY, 'testing' )

suite = loader.discover( start_dir, test_pattern )
runner = unittest.TextTestRunner( verbosity=2 )
results = runner.run( suite )

print( "results: %s" % results )
print( "results.wasSuccessful: %s" % results.wasSuccessful() )

sys.exit( not results.wasSuccessful() )

참고 문헌 :

  1. unittest 모듈이 스크립트에있을 때 sys.argv [1] 관련 문제
  2. 파이썬 클래스에서 모든 함수를 반복하고 실행하는 방법이 있습니까?
  3. 파이썬에서 클래스의 모든 멤버 변수를 반복

마지막 주 프로그램 예제 대신에 unittest.main()메소드 구현 을 읽은 후 다음과 같은 변형이 발생했습니다 .

  1. https://github.com/python/cpython/blob/master/Lib/unittest/main.py#L65
#! /usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import sys
import unittest

PACKAGE_ROOT_DIRECTORY = os.path.dirname( os.path.realpath( __file__ ) )
start_dir = os.path.join( PACKAGE_ROOT_DIRECTORY, 'testing' )

from testing_package import main_unit_tests_module
testNames = ["TestCaseClassName.test_nameHelloWorld"]

loader = unittest.TestLoader()
suite = loader.loadTestsFromNames( testNames, main_unit_tests_module )

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

print( "results: %s" % results )
print( "results.wasSuccessful: %s" % results.wasSuccessful() )
sys.exit( not results.wasSuccessful() )

3

TL; DR : 다음과 같이 작동합니다.

python mypkg/tests/test_module.py MyCase.testItIsHot

설명 :

  • 편리한 방법

    python mypkg/tests/test_module.py MyCase.testItIsHot

    그러나 작동하지 않을 것이라고 가정하면 테스트 파일 내부 (일반적으로 끝 부분) 에이 일반적인 코드 스 니펫이 이미 있다는 것입니다.

    if __name__ == "__main__":
        unittest.main()
  • 불편한 방법

    python -m unittest mypkg.tests.test_module.TestClass.test_method

    if __name__ == "__main__": unittest.main()테스트 소스 파일에 해당 코드 스 니펫 을 요구하지 않고 항상 작동 합니다.

그렇다면 왜 두 번째 방법이 불편하다고 생각합니까? 그것은 (_에 통증이 될 것 때문에 여기 본문 부분 삽입 한 긴 것을 입력 할 _), 손으로 경로를 구분 도트. 첫 번째 방법에서는 mypkg/tests/test_module.py최신 쉘 또는 편집기를 통해 파트를 자동 완성 할 수 있습니다.

추신 : 신체 부위 가 허리 아래에 있다고 생각 하면 진정한 사람입니다. :-) "손가락 관절"이라고합니다. 타이핑이 너무 많으면 관절에 좋지 않습니다. ;-)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.