[英]defining a one-off class within python unittest
如果这是重复的操作,请随时关闭,但是到目前为止,我还没有看到任何类似的消息。 我更多地是来自“经典OOP”背景(例如Java,C#,C ++,PHP(如果您想将其称为OOP语言...)等),而我现在正在尝试掌握Python。
假设我们有一个这样定义的类:
class Foo:
def __init__(self):
self.stuff = self.defineStuff()
def method1(self, x):
return x
def defineStuff(self):
# this method has no logic in this class; child classes should define this
pass
def doStuff(self):
return self.stuff
class FooTest(unittest.TestCase):
def testMethod1(self):
assertEquals(5, Foo().method1(5))
好的,到目前为止很好。 但是,我真正要测试的是doStuff
可以正常工作; 上面的实现本身可能太琐碎了,但是我没有在这里发布我的实际代码。 由于doStuff
依靠defineStuff
来填充stuff
成员变量,因此测试Foo.doStuff()
是没有意义的,除非我要测试基类实现是否抛出AttributeError。 (这是有效的,但实际上不是我要测试的内容)。 但是,我可以执行以下操作:
class FooTest(unittest.TestCase):
# we did this before, it's just here for reference
def testMethod1(self):
assertEquals(5, Foo().method1(5))
def testDefineStuff(self):
class Bar(Foo):
def defineStuff(stuff):
self.stuff = stuff
return self
bar = Bar().defineStuff('abcdefg')
self.assertEquals('abcdefg', bar.stuff)
我已经尝试在setUp()方法中定义Bar类,并且将其作为FooTest类中的单独方法进行定义,并且在尝试使用该类之前,都无法定义该类。 我收到一个NameError异常。 我是否被迫在每个测试方法中定义Bar类,或者我缺少什么? Bar类应该是一个测试装置。 我不打算在测试之外使用它,但是它确实演示了Foo父类的具体功能。 我的示例是人为的并且过于简化,但是我的意思是,我不想为Bar类定义一个单独的类文件,因为它仅用于测试。
如果我在FooTest类定义中定义了Bar类,这行得通吗? Python在Java中是否具有等效的内部类?
这让我想起了PHPUnit的模拟对象。 我相信unittest模块不支持它们,但是也许有些插件可以为您提供此功能,这肯定比滚动您自己的解决方案更好,我会首先尝试找到这种插件。
无论如何,Python是非常通用的,尤其是它的类也是对象! 因此,您可以执行以下操作:
class FooTest(unittest.TestCase):
def setUp(self):
class Bar(Foo):
def defineStuff(stuff):
self.stuff = stuff
return self
# store class locally
self.Bar = Bar
def testDefineStuff(self):
bar = self.Bar().defineStuff('abcdefg')
self.assertEquals('abcdefg', bar.stuff)
关于您有关嵌套类的问题,我不知道,只需尝试一下即可。 请记住,尽管其他几种语言的隐式作用域(即在this
为可选)不是Python的功能/故障之一,所以您始终必须将嵌套类称为self.Bar
或FooTest.Bar
。
我解释了昨晚我所做的相当糟糕的尝试(在凌晨4点发布问题可能不是最明智的想法)。 考虑到我的示例出现的方式,这些评论是有效的。
下面的Foo类比我的原始示例简单一些:
class Foo:
def __init__(self):
self.stuff = self.defineStuff()
def defineStuff(self):
return []
def doStuff(self):
try:
return [x + x for x in self.stuff]
except TypeError:
raise FooException("defineStuff must return a list")
class FooTest(unittest.TestCase):
def testDoStuff(self):
v = Foo().doStuff()
self.assertEquals([], v)
因此,这里的defineStuff
方法没有存根,而是返回它可以的最基本值,因为该类是要扩展的。 现在实际上测试doStuff
甚至defineStuff
确实有意义,因为这两种方法实际上都已实现。
回到我试图问与我原来的问题...正如我在评论中提到的,我不打算给这个项目的范围内定义子类。 (我确实打算在其他项目中这样做,但是我想知道该项目在继续之前会按预期工作。)因此,即使使用实际值定义了defineStuff
,我仍然不知道如果更复杂的情况会起作用。
如果子类将defineStuff
定义为返回[[1,2], [3,4], [5,6]]
defineStuff
[[1,2], [3,4], [5,6]]
怎么办? 我是否知道这可以正常工作并返回[[1, 2, 1, 2], [3, 4, 3, 4], [5, 6, 5, 6]]
? 从理论上讲,应该。 这个例子特别简单,我可以看一下并知道它会。 但是我还没有对它进行确定的测试,并且我不想定义一个单独的子类来这样做,因为我永远不会使用它。
关于是否可以在unittest.TestCase派生的类的setUp方法中定义类并让其被您的测试方法识别的问题,尚无定论。 但是,我意识到我可以按照以下方式进行操作:
class FooTest(unittest.TestCase):
@staticmethod
def sampleStuff(placeholder):
return [[1, 2], [3, 4], [5, 6]]
def testDoStuff(self):
Foo.defineStuff = FooTest.sampleStuff
v = Foo().doStuff()
self.assertEquals([[1, 2, 1, 2], [3, 4, 3, 4], [5, 6, 5, 6]], v)
因此,通过这种方式,我不需要定义一次性测试类来进行测试,但是我可以至少涵盖客户端可以定义defineStuff
的可能方式的子集。 我将无法涵盖所有内容,而且我也不打算这样做,但是我可以做的测试用例越多,我就至少可以肯定地确定我的逻辑能够按预期工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.