TypeError:未绑定的方法__init __()....在重新打包后的单元测试期间

时间:2010-08-01 20:34:59

标签: python testing package

我刚刚重新包装了我的程序。以前所有模块都在“whyteboard”包下,带有一个包含一堆虚拟GUI测试对象的“fakewidgets”包。

现在,我的所有模块都在包中,例如whyteboard.gui,whyteboard.misc,whyteboard.test - 这就是fakewidgets现在所在的地方。

现在,在运行我的测试时,我得到一个例外,

  File "/home/steve/Documents/whyteboard/whyteboard/gui/canvas.py", line 77, in __init__
    wx.ScrolledWindow.__init__(self, tab, style=wx.NO_FULL_REPAINT_ON_RESIZE | wx.CLIP_CHILDREN)
TypeError: unbound method __init__() must be called with ScrolledWindow instance as first argument (got Canvas instance instead)

这里的  有问题的课程

class Canvas(wx.ScrolledWindow):
    def __init__(self, tab, gui, area):
        wx.ScrolledWindow.__init__(self, tab, style=wx.NO_FULL_REPAINT_ON_RESIZE | wx.CLIP_CHILDREN)

但是,我的程序加载并正确运行,除了单元测试。代码是一样的,只是我的测试导入的代码与新软件包的输入不同。

在:

import os
import wx

import fakewidgets
import gui
import lib.mock as mock

from canvas import Canvas, RIGHT, DIAGONAL, BOTTOM
from fakewidgets.core import Bitmap, Event, Colour

from lib.configobj import ConfigObj
from lib.pubsub import pub
from lib.validate import Validator

现在:

import os
import wx

import whyteboard.test
import whyteboard.gui.frame as gui

from whyteboard.lib import ConfigObj, mock, pub, Validator
from whyteboard.gui.canvas import Canvas, RIGHT, DIAGONAL, BOTTOM
from whyteboard.test.fakewidgets.core import Bitmap, Event, Colour, PySimpleApp

值得注意的是,fakewidgets包有一些技巧让我的程序认为它使用的是wxPython类,即使它们是模拟的。 这是来自whyteboard.test.fakewidgets'__init__

导入的模块
class Window(object):
    def __init__(self, parent, *args, **kwds):
        self.parent = parent
        self.Enabled = True
        self.calls = []
        self.size = (0, 0)
        self.captured = False

    def GetClientSizeTuple(self):
        return (0, 0)
        self.captured = True

    def GetId(self):
        pass

    def Fit(self):
        pass

    def SetFocus(self):
        pass

    def PrepareDC(self, dc):
        pass

    def Destroy(self):
        pass

...


class ScrolledWindow(Window):
    def SetVirtualSize(self, *size):
        pass

    def SetVirtualSizeHints(self, *size):
        pass

import wx
wx.__dict__.update(locals())

4 个答案:

答案 0 :(得分:3)

当你import whyteboard.test时,会自动运行whyteboard.test.fakewidgets.core吗?我认为问题是在模拟代码运行之前正在创建{em} {em}。这解释了转换。

Canvas

在您发布的旧文件中,>>> import wx >>> class Test1(wx.Window): ... pass ... >>> wx.Window = object >>> class Test2(wx.Window): ... pass ... >>> dir(Test1)[:10] ['AcceleratorTable', 'AcceptsFocus', 'AcceptsFocusFromKeyboard', 'AddChild', 'AddPendingEvent', 'AdjustForLayoutDirection', 'AssociateHandle', 'AutoLayout', 'BackgroundColour', 'BackgroundStyle'] >>> dir(Test2)[:10] ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__'] 之前已导入fakewidgets

如果这不起作用,请在canvas之后直接将此代码放在任何其他导入之前:

import wx

这将显示在模拟到位之前正在创建import inspect class DummyMeta(type): def __new__(meta, clsname, bases, clsdict): if clsname == 'Canvas': lineno = inspect.stack()[1][2] print "creating Canvas with mro: {0}".format(inspect.getmro(bases[0])) print "file:{0}:{1}".format(__file__, lineno) return super(DummyMeta, meta).__new__(meta, clsname, bases, clsdict) class ScrolledWindowDummy(wx.Window): __metaclass__ = DummyMeta wx.ScrolledWindow = ScrolledWindowDummy 类,并将为您提供发生此情况的文件和行号。实质上,对于MRO,你不应该看到Canvas的任何内容。如果我错了,那么你根本就不会看到任何东西,因为在创建任何名为“Canvas”的类之前,你将用一个没有类型wx的类替换ScrolledWindowDummy

答案 1 :(得分:1)

  

代码是一样的,只是我的测试导入的代码与新软件包的输入不同

这听起来好像你的进口正在进口你没想到的东西。一旦我将一个文件命名为与系统模块相同的文件。我花了几个小时才弄清楚出了什么问题。

查看更改sys.path时会发生什么。

答案 2 :(得分:1)

请在wx的定义之前打印wx.ScrolledWindowclass Canvas,并将其作为Canvas.__init__的第一行。我强烈怀疑这些会有所不同。

您是否正在使用__new__或元类等进行任何欺骗?

答案 3 :(得分:1)

确保fakewidgets是第一个导入wx模块,这意味着导入顺序很重要,例如。

import fakewidgets
import wx

或者,代替 dict .update技巧,明确替换名称,即

import wx

wx.Window = Window
# for all other relevant widgets

同样,仍然要确保fakewidgets是第一个访问wx模块的人。