2

这是我最近制作的工具中的代码,我正在尝试编写单元测试,我知道如何测试返回某些东西的方法,但不明白我应该如何测试不喜欢下面的方法:

def buildUi(self):
    self.label = QtGui.QLabel()
    self.label.setAlignment(QtCore.Qt.AlignCenter)
    self.setCentralWidget(self.label)

def nextImage(self):
    """ switch to next image or previous image
    """
    if self._imagesInList:
        if self._count == len(self._imagesInList):
            self._count = 0

        self.showImageByPath(
                self._imagesInList[self._count])

        if self.animFlag:
            self._count += 1
        else:
            self._count -= 1


def showImageByPath(self, path):
    if path:
        image = QtGui.QImage(path)
        pp = QtGui.QPixmap.fromImage(image)
        self.label.setPixmap(pp.scaled(
                self.label.size(),
                QtCore.Qt.KeepAspectRatio,
                QtCore.Qt.SmoothTransformation))

def playPause(self):
    if not self._pause:
        self._pause = True
        self.updateTimer.start(2500)
        return self._pause
    else:
        self._pause = False
        self.updateTimer.stop()

def keyPressEvent(self, keyevent):
    """ Capture key to exit, next image, previous image,
        on Escape , Key Right and key left respectively.
    """
    event = keyevent.key()
    if event == QtCore.Qt.Key_Escape:
        self.close()
    if event == QtCore.Qt.Key_Left:
        self.animFlag = False
        self.nextImage()
    if event == QtCore.Qt.Key_Right:
        self.animFlag = True
        self.nextImage()
    if event == 32:
        self._pause = self.playPause()

可以在这里找到完整的查找代码

是否可以在上面测试这些方法,或者我是否必须修改以使它们可测试?编辑:更新:

class TestSlideShow(unittest.TestCase):
    """ docstring for TestSlideShow
    """
    def setUp(self):
        self.mox = mox.Mox()
        self.imgLst = ['/folder/test/images/test1.jpg', '/folder/test/images/test2.JPG',
        '/folder/test/images/test3.png', '/folder/test/images/test4.PNG']
        app = QtGui.QApplication([])
        self.show = slideShow.SlideShowPics(imgLst=self.imgLst, ui=False)

def tearDown(self):
    self.mox.UnsetStubs()
    self.mox.ResetAll()

def test_nextImage(self):
    self.mox.StubOutWithMock(self.show, 'prepairWindow')
    self.show.prepairWindow()
    self.mox.StubOutWithMock(self.show, 'showImageByPath')
    self.show.showImageByPath(self.imgLst[1])
    self.show.nextImage()
    # self.mox.ReplayAll()
    self.assertEquals(1, self.show.count)
    self.assertEquals(self.imgLst[1], self.show._imagesInList[1])
    # self.mox.VerifyAll()

def test_nextImage_animFlag_False(self):
    self.show.animFlag = False
    self.show.count = 4

    self.mox.StubOutWithMock(self.show, 'prepairWindow')
    self.show.prepairWindow()
    self.mox.StubOutWithMock(self.show, 'showImageByPath')
    self.show.showImageByPath(self.imgLst[3])
    print self.show.count
    self.show.nextImage()
    print self.show.count       
    # self.assertEquals(3, self.show.count)
    self.assertEquals(self.imgLst[3], self.show._imagesInList[3])


if __name__ == '__main__':
    unittest.main()

self.show.animFlag 为 True 时的第一个测试工作正常,但是当我手动设置 animFlag= False 时,第二个测试失败。

4

1 回答 1

2

这是在代码之后编写 unittest 的问题 - 然后您会意识到您的代码很难测试。在代码之前编写测试(嗯,真的是“沿着”代码——你不会在开始编码之前编写所有测试,但你仍然不会在测试之前编写一行代码)确保你没有有这样的问题。

现在,即使使用“测试优先”方法,您也必须测试不返回任何内容的方法。这样做的方法是测试预期的副作用。其中一些副作用很容易测试 - 在上述情况下,您可以根据对象的状态(并且主要是)测试self._count调用之前和之后的值。变得更加困难的地方是,如果您想测试确实使用正确的参数进行调用,并且使用您当前的设计,唯一的方法是为测试进行猴子补丁。测试将需要修补/模拟等。nextImage_imagesInListanimFlagnextImageshowImageByPathshowImageByPathshowImageByPathself.label.setPixmap()

正如其他人已经指出的那样,有几个模拟/存根库可以提供帮助,但它们不会解决所有可能的可测试性问题,您可能需要重新考虑您的设计以使事情变得更容易——比如不硬编码对 in 的调用QtGui.QLabel()buildUI()但有一些方法改为“注入”所需的组件(QtGui.QLabel()或模拟)。作为一般规则,可测试的代码几乎没有硬编码的依赖关系,很少有副作用,并且有很多带有短方法的小类(而不是带有长方法的大类)。

于 2013-11-23T14:07:49.050 回答