我应该如何测试不返回任何内容的方法?

时间:2013-11-23 13:48:00

标签: python unit-testing testing ui-testing

这是我最近的工具中的代码,我正在尝试编写unittest,我有一个idea of how to test a method that returns something但不明白我应该如何测试不喜欢下面的方法:

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()

可以找到完整的查找代码here

可以测试上面的这些方法,还是我必须修改才能使它们可测试? 编辑:更新:

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然后第二次测试失败时。

1 个答案:

答案 0 :(得分:1)

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

现在即使使用“先测试”方法,您也必须测试不返回任何内容的方法。这样做的方法是测试预期的副作用。其中一些副作用很容易测试 - 在上述情况下,您可以在调用self._count之前和之后测试nextImage的值,具体取决于对象的状态(_imagesInList和主要是animFlag。如果你想测试nextImage实际上是否使用正确的参数调用showImageByPath,并且使用当前设计,唯一的方法就是monkeypatch showImageByPath测试。测试showImageByPath需要修补/模拟self.label.setPixmap()等。

正如其他人已经指出的那样,有一些模拟/存根库可以提供帮助,但它们无法解决所有可能的可测试性问题,您可能不得不重新考虑您的设计以使事情变得更容易 - 就像没有硬编码调用{{ 1}}在QtGui.QLabel()中,但有一些方法来“注入”所需的组件(buildUI()或模拟)。作为一般规则,可测试代码具有非常少的硬编码依赖性,很少的副作用,以及许多具有短方法的小类(而不是具有长方法的大类)。