기본 및 하위 클래스를 사용한 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 개만 실행하려고합니다. 파이썬 unittest는 독자적인 BaseTest를 자체적으로 실행하고있는 것으로 보이며 그 발생을 막기위한 메커니즘이 필요합니다.
다중 상속을 사용하므로 일반적인 테스트를 수행하는 클래스 자체는 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()
다중 상속을 사용하지 마십시오 . 나중에 물릴 것 입니다.
대신 기본 클래스를 별도의 모듈로 옮기거나 빈 클래스로 래핑 할 수 있습니다.
import unittest
class BaseTestCases:
class BaseTest(unittest.TestCase):
def testCommon(self):
print 'Calling BaseTest:testCommon'
value = 5
self.assertEquals(value, 5)
class SubTest1(BaseTestCases.BaseTest):
def testSub1(self):
print 'Calling SubTest1:testSub1'
sub = 3
self.assertEquals(sub, 3)
class SubTest2(BaseTestCases.BaseTest):
def testSub2(self):
print 'Calling SubTest2:testSub2'
sub = 4
self.assertEquals(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
단일 명령으로이 문제를 해결할 수 있습니다.
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의 대답은 훌륭하지만 각 테스트 사례에서 오류가 발생하기 쉬운 두 클래스에서 상속해야합니다. 대신, 나는 이것을 사용합니다 (python> = 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
그래서 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부터 건너 뛰려는 모든 테스트 메소드에서 @ unittest.skip () 데코레이터를 사용할 수 있습니다.
http://docs.python.org/library/unittest.html#skipping-tests-and-expected-failures
기본 유형을 확인하려면 자체 건너 뛰기 데코레이터를 구현해야합니다. 이 기능을 전에 사용하지는 않았지만 머리 꼭대기에서 BaseTest를 마커 유형으로 사용하여 건너 뛰기를 조정할 수 있습니다 .
def skipBaseTest(obj):
if type(obj) is BaseTest:
return unittest.skip("BaseTest tests skipped")
return lambda func: func
내가 이것을 해결하려고 생각한 방법은 기본 클래스가 사용되는 경우 테스트 메소드를 숨기는 것입니다. 이렇게하면 테스트를 건너 뛰지 않으므로 많은 테스트보고 도구에서 테스트 결과가 노란색 대신 녹색이 될 수 있습니다.
PyCharm과 같은 ide는 mixin 메소드와 비교할 때 단위 테스트 메소드가 기본 클래스에서 누락되었다고 불평하지 않습니다.
기본 클래스가이 클래스에서 상속되면 setUpClass
and 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
__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()
@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())
그리고 우리는 간다.
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()`
그래서 이것은 일종의 오래된 스레드이지만 오늘이 문제를 겪고 내 자신의 해킹을 생각했습니다. 기본 클래스를 통해 액세스 할 때 None 함수 값을 만드는 데코레이터를 사용합니다. 기본 클래스에 테스트가 없으면 실행되지 않으므로 설정 및 설정 클래스에 대해 걱정할 필요가 없습니다.
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()
As of Python 3.2, you can add a test_loader function to a module to control which tests (if any) are found by the test discovery mechanism.
For example, the following will only load the original poster's SubTest1
and SubTest2
Test Cases, ignoring Base
:
def load_tests(loader, standard_tests, pattern):
suite = TestSuite()
suite.addTests([SubTest1, SubTest2])
return suite
It ought to be possible to iterate over standard_tests
(a TestSuite
containing the tests the default loader found) and copy all but Base
to suite
instead, but the nested nature of TestSuite.__iter__
makes that a lot more complicated.
Change the BaseTest method name to 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)
Output:
Ran 2 tests in 0.000s
Calling BaseTest:testCommon Calling
SubTest1:testSub1 Calling
BaseTest:testCommon Calling
SubTest2:testSub2
From the documentation:
TestCase.setUp()
Method called to prepare the test fixture. This is called immediately before calling the test method; any exception raised by this method will be considered an error rather than a test failure. The default implementation does nothing.
참고URL : https://stackoverflow.com/questions/1323455/python-unit-test-with-base-and-sub-class
'Programing' 카테고리의 다른 글
프로그래밍 방식으로 UIImageView에 표시되는 이미지를 어떻게 변경할 수 있습니까? (0) | 2020.06.27 |
---|---|
마스터와 슬레이브에 MySQL 복제의 경우 다른 데이터베이스가있는 경우 MySQL 데이터베이스를 다시 동기화하는 방법은 무엇입니까? (0) | 2020.06.27 |
유튜브 iframe W 모드 문제 (0) | 2020.06.27 |
페이지가 화면보다 큰 경우 화면 중간에 div를 배치하는 방법 (0) | 2020.06.27 |
64 비트 Windows에 SetupTools 설치 (0) | 2020.06.27 |