Unittest Tkinter文件对话框


问题内容

有什么办法可以自动执行tkFileDialog选择unittest吗?以下是tkinter我的应用程序中的唯一用法:

root = Tkinter.Tk()
types = [('Comma Separated Values', '.csv'), ('All Files', '*')]
filename = tkFileDialog.askopenfilename(parent=root,
                                        filetypes=types)
root.destroy()

编辑 :我没有提到这部分代码被困在我控制范围之外的类的方法调用中。


背景

我已经构建了一个本地应用程序,该应用程序在http服务器上创建了一个HTTP服务器,localhost并在Web浏览器中使用HTML / CSS /
JS运行其GUI。由于浏览器的限制,我无法使用内置文件对话框,因此必须通过Python发送此请求。我希望它可以在带有内置Python
2.5的OSX上运行。我不是很熟悉Tcl/Tk

尝试#1

如果我可以访问基础小部件,则可以生成此问题中的点击。但是,从对话源看,在我看来,第Tcl48-50行的呼叫正在阻塞。这是正确的假设吗?

尝试#2

我认为可能有一种Tcl直接通过使用命令的方法root.tk.call。自从我上班以来Python2,我认为底层Tcl就是对tk_getOpenFile。我是否必须确保Tcl解释器已线程化?有什么Tcl/Tk命令可以帮助我吗?

尝试#3

我可以使用os.listdir等等从头开始实现文件选择。(可能在与服务器来回通信的单独HTML页面中)。这将不仅仅是痛苦的而且希望是可以避免的。


根据A. Rodas的以下回答,我提出了以下建议:

import tkFileDialog
old_dialog = tkFileDialog.askopenfilename
try:
    tkFileDialog.askopenfilename = lambda *args, **kw: filename

    # First test dialog cancelled
    filename = ''
    method_that_calls_tk()
    # run some assertions

    # Next test a valid file name with valid contents
    filename = self.VALID_FILENAME
    method_that_calls_tk()
    # run some assertions

    # Now test a valid file name with invalid contents
    filename = self.INVALID_CONTENTS_FILENAME
    method_that_calls_tk()
    # run some assertions

    # Now test an invalid file name
    filename = self.INVALID_FILENAME
    method_that_calls_tk()
    # run some assertions
finally:
    tkFileDialog.askopenfilename = old_dialog

问题答案:

Tkinter代码的单元测试不是一个容易的问题。例如,IDLE没有适当的测试套件,即使它是标准库的一部分。既然您提到这将是Tkinter在您的应用程序中的唯一用法,所以我建议对此代码的结果进行单元测试:的值filename

例如,您可以测试一个.csv文件,另一个测试不正确的文件扩展名。由于tkFileDialog返回一个空字符串,如果它被用户关闭,还可以添加一个测试,filename = ''

import unittest

class TestFileDialog(unittest.TestCase):

    def test_dialog_closed(self):
        filename = ''
        # ...

    def test_incorrect_extension(self):
        filename = '/path/to/another/filetype'
        # ...

    def test_csv_extension(self):
        filename = '/path/to/correct/file.csv'
        # ...