对 tkinter 应用程序进行单元测试

unittesting a tkinter application

我正在尝试为我编写的 Tkinter 应用程序实施单元测试(同时了解它们)。为此,我设法围绕我的应用程序的基本结构创建了一个非常简约的单元测试,如下所示(将 Tkinter 实例作为 master 传递给它):

classTest.py

#! /usr/bin/env python
from Tkinter import *

class App():
    def __init__(self,master):
        self.text = "foo"
        self.printy()

    def printy(self):
        print self.text
        return "test"

# Call the main app
if __name__ == "__main__":
    root = Tk()
    app = App(root)
    root.mainloop()

test.py

#! /usr/bin/env python
from Tkinter import *
import unittest
import classTest

class testTest(unittest.TestCase):
    def test(self):
        a = classTest.App(Tk())
        self.assertEqual(a.printy(),"test")

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

这个测试 returns 它 运行 成功了,尽管它打印了 foo 两次。但是,当我随后尝试在我的整个应用程序中 运行 相同的概念时,它在我的 class.

__init__ 上崩溃了

unitTest.py

#! /usr/bin/env python
import unittest
from Tkinter import *
import MassyTools

class readTest(unittest.TestCase):
    def test(self):
        a = MassyTools.App(Tk())
        self.assertEqual(a.readData("./tests/calibrated_IBD cohort sample H6-run 1_0_E24_1.xy")[0][0],1299.11)

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

运行 这个测试因为没有定义 root 而崩溃(见下面的错误)。

我一直在根据这个 blogpost 摆弄模拟,但我还没有真正掌握这个概念。下面是 MassyTools.py 文件的一个子集,包括有问题的 self.toolbar 行:

class App():

    def __init__(self, master):
        # The Canvas
        self.canvas = FigureCanvasTkAgg(self.fig, master=master)
        self.toolbar = NavigationToolbar2TkAgg(self.canvas, root)
        self.canvas.get_tk_widget().pack(fill=BOTH, expand=YES)
        self.canvas.draw()

因此,问题是我是否应该在单元测试中以不同的方式实例化它,修改应用程序以在以这种方式或其他方式完全调用时具有假根。

我在我想测试的应用程序中发现了问题,我在 main 中声明了 root = Tk()。这个 root 作为 master 传递给 App class 但在程序中我调用了 root 它应该是 master ].以下更改消除了初始崩溃,我还包括对 atexit 的调用,以便不必物理关闭应用程序(根据 this 回答)。

修改后的申请:

class App():

    def __init__(self, master):

        # The Canvas
        self.canvas = FigureCanvasTkAgg(self.fig, master=master)
        self.toolbar = NavigationToolbar2TkAgg(self.canvas, master)
        self.canvas.get_tk_widget().pack(fill=BOTH, expand=YES)
        self.canvas.draw()

# Call the main app
if __name__ == "__main__":
    root = Tk()
    app = App(root)
    root.mainloop()

我按如下方式调整了我的 unittest.py 代码,现在在我实际关闭应用程序后以 OK 结束:

#! /usr/bin/env python
import unittest
from Tkinter import *
import MassyTools
import atexit

class readTest(unittest.TestCase):
    def test(self):
        self.assertEqual(a.readData("./tests/calibrated_IBD cohort sample H6-run 1_0_E24_1.xy")[0][0],1299.11)

if __name__ == "__main__":
    # Set up Tk(), instantiate the application and close it right away.
    root = Tk()
    a = MassyTools.App(root)
    atexit.register(root.mainloop)
    root.destroy()

    # Start the actual tests
    unittest.main(verbosity=2)