gru*_*czy 47 python unit-testing testcase
是否有可能创建一个抽象TestCase,它将有一些test_*方法,但这TestCase不会被调用,那些方法只会在子类中使用?我想我将TestCase在我的测试套件中有一个摘要,它将被子类化为单个接口的一些不同实现.这就是为什么所有测试方法都是一些,只有一个内部方法发生变化的原因.我怎么能以优雅的方式做到这一点?
jsb*_*eno 64
我不太明白你打算做什么 - 经验法则是"不要用测试来聪明" - 只要把它们放在那里,写得很清楚.
但是要实现你想要的,如果你继承自unittest.TestCase,每当你调用unittest.main()时你的"抽象"类都会被执行 - 我认为这是你想要避免的情况.
只需这样做:创建继承自"object"的"抽象"类,而不是TestCase.对于实际的"具体"实现,只需使用多重继承:从unittest.TestCase和您的抽象类继承.
import unittest
class Abstract(object):
def test_a(self):
print "Running for class", self.__class__
class Test(Abstract, unittest.TestCase):
pass
unittest.main()
Run Code Online (Sandbox Code Playgroud)
更新:颠倒继承顺序 - Abstract首先,TestCase默认情况下不会覆盖其定义,并在下面的注释中指出.
tsu*_*una 13
多重继承在这里不是一个很好的选择,主要是出于以下两个原因:
TestCase用super(),所以你不得不先列出你的类类似的方法setUp()和tearDown()工作.self.assertEquals()等self在该点未定义的等.这是我想出来的kludge:只变成run()基类的无操作.
class TestBase( unittest.TestCase ):
def __init__( self, *args, **kwargs ):
super( TestBase, self ).__init__( *args, **kwargs )
self.helper = None
# Kludge alert: We want this class to carry test cases without being run
# by the unit test framework, so the `run' method is overridden to do
# nothing. But in order for sub-classes to be able to do something when
# run is invoked, the constructor will rebind `run' from TestCase.
if self.__class__ != TestBase:
# Rebind `run' from the parent class.
self.run = unittest.TestCase.run.__get__( self, self.__class__ )
else:
self.run = lambda self, *args, **kwargs: None
def newHelper( self ):
raise NotImplementedError()
def setUp( self ):
print "shared for all subclasses"
self.helper = self.newHelper()
def testFoo( self ):
print "shared for all subclasses"
# test something with self.helper
class Test1( TestBase ):
def newHelper( self ):
return HelperObject1()
class Test2( TestBase ):
def newHelper( self ):
return HelperObject2()
Run Code Online (Sandbox Code Playgroud)
jro*_*aud 11
如果你真的想使用继承而不是mixin,一个简单的解决方案是将抽象测试嵌套在另一个类中。
它避免了测试运行程序发现的问题,您仍然可以从另一个模块导入抽象测试。
import unittest
class AbstractTests(object):
class AbstractTest(unittest.TestCase)
def test_a(self):
print "Running for class", self.__class__
class Test(AbstractTests.AbstractTest):
pass
Run Code Online (Sandbox Code Playgroud)
到目前为止,每个人都错过了一种非常简单的方式.与几个答案不同,它适用于所有测试驱动程序,而不是在它们之间切换时失败.
像往常一样使用继承,然后添加:
del AbstractTestCase
Run Code Online (Sandbox Code Playgroud)
在模块的最后.
小智 7
只是为了加入我的2美分,虽然它可能违反某些约定,但您可以将您的抽象测试用例定义为受保护的成员以防止其执行.我在Django中实现了以下功能,并按要求工作.见下面的例子.
from django.test import TestCase
class _AbstractTestCase(TestCase):
"""
Abstract test case - should not be instantiated by the test runner.
"""
def test_1(self):
raise NotImplementedError()
def test_2(self):
raise NotImplementedError()
class TestCase1(_AbstractTestCase):
"""
This test case will pass and fail.
"""
def test_1(self):
self.assertEqual(1 + 1, 2)
class TestCase2(_AbstractTestCase):
"""
This test case will pass successfully.
"""
def test_1(self):
self.assertEqual(2 + 2, 4)
def test_2(self):
self.assertEqual(12 * 12, 144)
Run Code Online (Sandbox Code Playgroud)
unittest.SkipTest在setUpClass()只是另一种方法是提高unittest.SkipTest在setUpClass()基类和覆盖的setUpClass()子类中:
class BaseTestCase(TestCase):
@classmethod
def setUpClass(cls):
"Child classes must override this method and define cls.x and cls.y"
raise unittest.SkipTest
def test_x(self):
self.assertEqual(self.x * 3, self.x)
def test_y(self):
self.assertEqual(self.y * 3, self.y + self.y + self.y)
def test_z(self):
self.assertEqual(self.x + self.y, self.y)
class IntegerTestCase(BaseTestCase):
@classmethod
def setUpClass(cls):
cls.x = 0
cls.y = 2
class StringTestCase(BaseTestCase):
@classmethod
def setUpClass(cls):
cls.x = ''
cls.y = 'zuzuka'
Run Code Online (Sandbox Code Playgroud)
如果您需要使用定义自己的自定义 TestCasesetUpClass()并且需要调用super().setUpClass(),则可以定义自己的方法来“设置数据”并仅在该方法内引发 SkipTest:
class BaseTestCase(ThidPartyTestCase):
@classmethod
def setUpClass(cls):
super().setUpClass() # if ThirdPartyTestCase has own setUpClass()
cls.setUpTestCaseData()
@classmethod
def setUpTestCaseData(cls):
"Override and set up cls.x and cls.y here"
raise unittest.SkipTest
... # tests
class IntegerTestCase(BaseTestCase):
@classmethod
def setUpTestCaseData(cls):
cls.x = 0
cls.y = 2
Run Code Online (Sandbox Code Playgroud)
该模块提供了多个跳过测试unittest的选项。
我的首选解决方案是重写setUpClass“抽象”基类中的方法以unittest.SkipTest在需要时引发异常:
class BaseTestCase(unittest.TestCase):
@classmethod
def setUpClass(cls):
if cls is BaseTestCase:
raise unittest.SkipTest("%s is an abstract base class" % cls.__name__)
else:
super(BaseTestCase, cls).setUpClass()
Run Code Online (Sandbox Code Playgroud)