기본 및 하위 클래스를 사용한 Python 장치 테스트
저는 현재 공통된 테스트 세트를 공유하는 몇 가지 단위 테스트가 있습니다.다음은 예입니다.
import unittest
class BaseTest(unittest.TestCase):
def testCommon(self):
print 'Calling BaseTest:testCommon'
value = 5
self.assertEquals(value, 5)
class SubTest1(BaseTest):
def testSub1(self):
print 'Calling SubTest1:testSub1'
sub = 3
self.assertEquals(sub, 3)
class SubTest2(BaseTest):
def testSub2(self):
print 'Calling SubTest2:testSub2'
sub = 4
self.assertEquals(sub, 4)
if __name__ == '__main__':
unittest.main()
위의 출력은 다음과 같습니다.
Calling BaseTest:testCommon
.Calling BaseTest:testCommon
.Calling SubTest1:testSub1
.Calling BaseTest:testCommon
.Calling SubTest2:testSub2
.
----------------------------------------------------------------------
Ran 5 tests in 0.000s
OK
위의 내용을 다시 작성하여 첫 번째 것을testCommon호출되지 않습니까?
편집: 위의 5가지 테스트를 실행하는 대신 SubTest1의 2가지 테스트와 SubTest2의 2가지 테스트 중 4가지 테스트만 실행했으면 합니다.Python unittest는 자체적으로 원본 BaseTest를 실행하고 있는 것 같은데, 그런 일이 일어나지 않도록 장치가 필요합니다.
다중 상속을 사용하지 마십시오. 나중에 물어뜯을 수 있습니다.
대신 기본 클래스를 별도의 모듈로 이동하거나 빈 클래스로 묶으면 됩니다.
class BaseTestCases:
class BaseTest(unittest.TestCase):
def testCommon(self):
print('Calling BaseTest:testCommon')
value = 5
self.assertEqual(value, 5)
class SubTest1(BaseTestCases.BaseTest):
def testSub1(self):
print('Calling SubTest1:testSub1')
sub = 3
self.assertEqual(sub, 3)
class SubTest2(BaseTestCases.BaseTest):
def testSub2(self):
print('Calling SubTest2:testSub2')
sub = 4
self.assertEqual(sub, 4)
if __name__ == '__main__':
unittest.main()
출력:
Calling BaseTest:testCommon
.Calling SubTest1:testSub1
.Calling BaseTest:testCommon
.Calling SubTest2:testSub2
.
----------------------------------------------------------------------
Ran 4 tests in 0.001s
OK
공통 테스트가 있는 클래스 자체가 TestCase에서 상속되지 않도록 다중 상속을 사용합니다.
import unittest
class CommonTests(object):
def testCommon(self):
print 'Calling BaseTest:testCommon'
value = 5
self.assertEquals(value, 5)
class SubTest1(unittest.TestCase, CommonTests):
def testSub1(self):
print 'Calling SubTest1:testSub1'
sub = 3
self.assertEquals(sub, 3)
class SubTest2(unittest.TestCase, CommonTests):
def testSub2(self):
print 'Calling SubTest2:testSub2'
sub = 4
self.assertEquals(sub, 4)
if __name__ == '__main__':
unittest.main()
단일 명령으로 이 문제를 해결할 수 있습니다.
del(BaseTest)
코드는 다음과 같습니다.
import unittest
class BaseTest(unittest.TestCase):
def testCommon(self):
print 'Calling BaseTest:testCommon'
value = 5
self.assertEquals(value, 5)
class SubTest1(BaseTest):
def testSub1(self):
print 'Calling SubTest1:testSub1'
sub = 3
self.assertEquals(sub, 3)
class SubTest2(BaseTest):
def testSub2(self):
print 'Calling SubTest2:testSub2'
sub = 4
self.assertEquals(sub, 4)
del(BaseTest)
if __name__ == '__main__':
unittest.main()
Matthew Marshall의 답변은 훌륭하지만, 각 테스트 사례에서 오류가 발생하기 쉬운 두 개의 클래스를 상속해야 합니다.대신 다음을 사용합니다(예:>=2.7).
class BaseTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
if cls is BaseTest:
raise unittest.SkipTest("Skip BaseTest tests, it's a base class")
super(BaseTest, cls).setUpClass()
추가할 수 있습니다.__test__ = False클래스에 BaseTest 클에추가경우합추니다를 .__test__ = True파생 클래스에서 테스트를 실행할 수 있습니다.
import unittest
class BaseTest(unittest.TestCase):
__test__ = False
def testCommon(self):
print 'Calling BaseTest:testCommon'
value = 5
self.assertEquals(value, 5)
class SubTest1(BaseTest):
__test__ = True
def testSub1(self):
print 'Calling SubTest1:testSub1'
sub = 3
self.assertEquals(sub, 3)
class SubTest2(BaseTest):
__test__ = True
def testSub2(self):
print 'Calling SubTest2:testSub2'
sub = 4
self.assertEquals(sub, 4)
if __name__ == '__main__':
unittest.main()
당신은 무엇을 성취하려고 노력하고 있습니까? 코드 시험가 붙지 으로 시험 코드를 작성합니다.test그렇게unittest로드하지 않습니다.
import unittest
class CommonTests(unittest.TestCase):
def common_assertion(self, foo, bar, baz):
# whatever common code
self.assertEqual(foo(bar), baz)
class BaseTest(CommonTests):
def testCommon(self):
print 'Calling BaseTest:testCommon'
value = 5
self.assertEquals(value, 5)
class SubTest1(CommonTests):
def testSub1(self):
print 'Calling SubTest1:testSub1'
sub = 3
self.assertEquals(sub, 3)
class SubTest2(CommonTests):
def testSub2(self):
print 'Calling SubTest2:testSub2'
sub = 4
self.assertEquals(sub, 4)
if __name__ == '__main__':
unittest.main()
매튜의 대답은 제가 아직 2.5이기 때문에 사용해야 했던 대답입니다.그러나 2.7 이후에는 건너뛰고 싶은 모든 테스트 방법에 the @unittest.sk iptx 데코레이터를 사용할 수 있습니다.
http://docs.python.org/library/unittest.html#skipping-tests-and-expected-failures
기본 유형을 확인하려면 고유한 건너뛰기 장식기를 구현해야 합니다.이전에 이 기능을 사용해 본 적은 없지만, 기본 테스트를 마커 유형으로 사용하여 건너뛰기 조건을 지정할 수 있습니다.
def skipBaseTest(obj):
if type(obj) is BaseTest:
return unittest.skip("BaseTest tests skipped")
return lambda func: func
이 문제를 해결하기 위해 생각한 방법은 기본 클래스를 사용할 경우 테스트 방법을 숨기는 것입니다.이렇게 하면 테스트를 건너뛸 수 없으므로 많은 테스트 보고 도구에서 테스트 결과가 노란색이 아닌 녹색이 될 수 있습니다.
믹스인 방식과 비교했을 때, 아이디어는 PyCharm이 기본 클래스에서 단위 테스트 방법이 누락되었다고 불평하지 않을 것입니다.
기본 클래스가 이 클래스에서 상속되는 경우 다음을 재정의해야 합니다.setUpClass그리고.tearDownClass방법들.
class BaseTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls._test_methods = []
if cls is BaseTest:
for name in dir(cls):
if name.startswith('test') and callable(getattr(cls, name)):
cls._test_methods.append((name, getattr(cls, name)))
setattr(cls, name, lambda self: None)
@classmethod
def tearDownClass(cls):
if cls is BaseTest:
for name, method in cls._test_methods:
setattr(cls, name, method)
cls._test_methods = []
다른 옵션은 실행하지 않는 것입니다.
unittest.main()
대신에 당신은 사용할 수 있습니다.
suite = unittest.TestLoader().loadTestsFromTestCase(TestClass)
unittest.TextTestRunner(verbosity=2).run(suite)
그래서 당신은 수업에서 테스트만 실행합니다.TestClass
다음은 문서화된 단위 테스트 기능만 사용하고 테스트 결과에 "건너뛰기" 상태가 되는 것을 방지하는 솔루션입니다.
class BaseTest(unittest.TestCase):
def __init__(self, methodName='runTest'):
if self.__class__ is BaseTest:
# don't run these tests in the abstract base implementation
methodName = 'runNoTestsInBaseClass'
super().__init__(methodName)
def runNoTestsInBaseClass(self):
pass
def testCommon(self):
# everything else as in the original question
작동 방식: 설명서에 따르면, "TestCase의 각 인스턴스는 methodName이라는 이름의 메서드인 단일 기본 메서드를 실행합니다."기본 "runTests"는 클래스의 모든 test* 메서드를 실행합니다. 이것이 TestCase 인스턴스의 일반적인 작동 방식입니다.그러나 추상 기본 클래스 자체에서 실행할 때는 아무 것도 하지 않는 메서드로 해당 동작을 재정의할 수 있습니다.
부작용으로는 테스트 횟수가 1회 증가한다는 것입니다. runNoTestsInBaseClass "test"는 BaseClass에서 실행될 때 성공적인 테스트로 계산됩니다.
(이 기능은 Python 2.7에서도 사용할 수 있습니다.그냥 바꾸기super()로.super(BaseTest, self).)
testCommon 메서드의 이름을 다른 메서드로 변경합니다.Unittest(일반적으로)는 'test'가 포함되지 않은 모든 항목을 건너뜁니다.
빠르고 간단하게
import unittest
class BaseTest(unittest.TestCase):
def methodCommon(self):
print 'Calling BaseTest:testCommon'
value = 5
self.assertEquals(value, 5)
class SubTest1(BaseTest):
def testSub1(self):
print 'Calling SubTest1:testSub1'
sub = 3
self.assertEquals(sub, 3)
class SubTest2(BaseTest):
def testSub2(self):
print 'Calling SubTest2:testSub2'
sub = 4
self.assertEquals(sub, 4)
if __name__ == '__main__':
unittest.main()`
저는 @Vladim P.(https://stackoverflow.com/a/25695512/2451329) 과 거의 동일하게 만들었지만 약간 수정했습니다.
import unittest2
from some_module import func1, func2
def make_base_class(func):
class Base(unittest2.TestCase):
def test_common1(self):
print("in test_common1")
self.assertTrue(func())
def test_common2(self):
print("in test_common1")
self.assertFalse(func(42))
return Base
class A(make_base_class(func1)):
pass
class B(make_base_class(func2)):
def test_func2_with_no_arg_return_bar(self):
self.assertEqual("bar", func2())
자, 시작합니다.
Python 3.2 이후에는 모듈에 test_loader 함수를 추가하여 테스트 검색 메커니즘에 의해 발견되는 테스트(있는 경우)를 제어할 수 있습니다.
예를 들어, 다음은 원본 포스터의 내용만 로드합니다.SubTest1그리고.SubTest2테스트 사례, 무시Base:
def load_tests(loader, standard_tests, pattern):
suite = TestSuite()
suite.addTests([SubTest1, SubTest2])
return suite
그것을 반복하는 것은 가능해야 합니다.standard_tests(a)TestSuite기본 로더에서 찾은 테스트 포함) 및 copy all butBase로.suite대신, 그러나 중첩된 특성TestSuite.__iter__훨씬 더 복잡하게 만듭니다.
이것은 일종의 오래된 스레드이지만 저는 오늘 이 문제를 접했고 그것을 위한 저만의 해킹을 생각했습니다.기본 클래스를 통해 액세스할 때 함수 값을 없음으로 만드는 장식기를 사용합니다.기본 클래스에 테스트가 없으면 실행되지 않으므로 설정 및 설정 클래스에 대해 걱정할 필요가 없습니다.
import types
import unittest
class FunctionValueOverride(object):
def __init__(self, cls, default, override=None):
self.cls = cls
self.default = default
self.override = override
def __get__(self, obj, klass):
if klass == self.cls:
return self.override
else:
if obj:
return types.MethodType(self.default, obj)
else:
return self.default
def fixture(cls):
for t in vars(cls):
if not callable(getattr(cls, t)) or t[:4] != "test":
continue
setattr(cls, t, FunctionValueOverride(cls, getattr(cls, t)))
return cls
@fixture
class BaseTest(unittest.TestCase):
def testCommon(self):
print('Calling BaseTest:testCommon')
value = 5
self.assertEqual(value, 5)
class SubTest1(BaseTest):
def testSub1(self):
print('Calling SubTest1:testSub1')
sub = 3
self.assertEqual(sub, 3)
class SubTest2(BaseTest):
def testSub2(self):
print('Calling SubTest2:testSub2')
sub = 4
self.assertEqual(sub, 4)
if __name__ == '__main__':
unittest.main()
기본 테스트 메서드 이름을 setUp:
class BaseTest(unittest.TestCase):
def setUp(self):
print 'Calling BaseTest:testCommon'
value = 5
self.assertEquals(value, 5)
class SubTest1(BaseTest):
def testSub1(self):
print 'Calling SubTest1:testSub1'
sub = 3
self.assertEquals(sub, 3)
class SubTest2(BaseTest):
def testSub2(self):
print 'Calling SubTest2:testSub2'
sub = 4
self.assertEquals(sub, 4)
출력:
0.000초 동안 두 번의 테스트 실행
호출 베이스 테스트:testCommon 호출
SubTest1:testSub1 호출
:testCommonCalling
파일 2:testSub2
설명서에서 다음을 참조하십시오.
테스트 사례.설정()
테스트 픽스처를 준비하기 위해 호출되는 메서드입니다.이는 테스트 방법을 호출하기 직전에 호출됩니다. 이 방법으로 발생한 예외는 테스트 실패가 아닌 오류로 간주됩니다.기본 구현에서는 아무런 작업도 수행하지 않습니다.
언급URL : https://stackoverflow.com/questions/1323455/python-unit-test-with-base-and-sub-class
'programing' 카테고리의 다른 글
| 스프링 부트 앱에서 META-INF/MANIFEST.MF 파일을 읽는 방법은 무엇입니까? (0) | 2023.06.28 |
|---|---|
| Git 저장소에서 삭제된 여러 파일을 제거하는 방법 (0) | 2023.06.28 |
| 복제된 원격 저장소와 원래 원격 저장소 간의 차이 (0) | 2023.06.28 |
| Spring의 @Autowired를 JUNIT 5 확장에서 작동하도록 만드는 방법은 무엇입니까? (0) | 2023.06.28 |
| SQL만 사용하여 SQL Server 2005 이미지 필드에 그림 삽입 (0) | 2023.06.28 |