【发布时间】:2012-02-08 21:40:29
【问题描述】:
对于使用App Engine testbed 的单元测试(使用unittest 模块),我需要setUp 和tearDown 方法来分别激活和停用测试台(稍微简化):
class SomeTest(unittest.TestCase):
def setUp(self):
self.testbed = testbed.Testbed()
self.testbed.activate()
def tearDown(self):
self.testbed.deactivate()
def testSomething(self):
...
这很快就会成为写作的负担。我可以编写一个基类TestCaseWithTestbed,但是每次我在一个测试用例中需要一个自定义setUp 时,我都必须记住调用超类方法。
我认为用类装饰器来解决这个问题会更优雅。所以我想写:
@WithTestbed
class SomeTest(unittest.TestCase):
def testSomething(self):
...
应用此装饰器后,测试平台应该会神奇地被激活。那么...如何实现WithTestbed 装饰器?我目前有以下:
def WithTestbed(cls):
class ClsWithTestbed(cls):
def setUp(self):
self.testbed = testbed.Testbed()
self.testbed.activate()
cls.setUp(self)
def tearDown(self):
cls.tearDown(self)
self.testbed.deactivate()
return ClsWithTestbed
这适用于简单的情况,但有一些严重的问题:
- 测试类的名称变为
ClsWithTestbed,并显示在测试输出中。 - 调用
super(SomeTestClass, self).setUp()的具体测试类最终会无限递归,因为SomeTestClass现在等于WithTestbed。
我对 Python 的运行时类型操作有点模糊。那么,如何以正确的方式做到这一点?
【问题讨论】:
-
不就是继承
setUp吗?普通的子类化有什么问题?为什么要为此搞砸装饰师? -
如果我在特定测试用例中还有其他设置任务要做,我必须记得致电
super(SomeTestCase, self).setUp()。太丑了。 -
它可能很难看,但它是标准的、常见的、正常的、Pythonic 的方法。
-
在
TestCases 中这样做并不常见。这很容易忘记,因为我刚刚做到了:) -
这在我的项目中很常见。我们有许多具有相似初始配置的测试用例。这可能很容易忘记,但一个常见的设置是一件大事,拥有适当的子类有助于组织它。这就是为什么
unittest框架——明确地——在本地语言中建立了适当的类层次结构。因此,您可以使用该语言(不是愚蠢的 DSL 或其他东西)来组织您的测试。简单继承是一个非常强大的工具。
标签: python google-app-engine decorator python-2.7