Is there any way to automate a tkFileDialog
selection to run it through unittest
? The following is the only use of tkinter
in my application:
root = Tkinter.Tk()
types = [('Comma Separated Values', '.csv'), ('All Files', '*')]
filename = tkFileDialog.askopenfilename(parent=root,
filetypes=types)
root.destroy()
Edit: I didn't mention that this part of the code was trapped in a method call from a class outside my control.
I've built a local app that creates an http server on localhost
and runs its GUI with HTML/CSS/JS in a web browser. Because of browser restrictions, I can't use the built-in file dialog and so have to send this request through Python. I want this to run on a OSX with the built-in Python 2.5. I'm not very familiar with Tcl/Tk
.
If I could get to the underlying widgets, I could generate the clicks like in this question. However, looking at the dialog source, it appears to me that the Tcl
call in lines 48-50 is blocking. Is this a correct assumption?
I thought there might be a way using Tcl
commands directly through root.tk.call
. Since I'm on Python2
, I think the underlying Tcl
is a single call to tk_getOpenFile
. Would I have to ensure the Tcl
interpreter is threaded? Is there any Tcl/Tk
command that can help me out here?
I could implement the file selection from scratch using os.listdir
etc. (Probably in a separate HTML page communicating back and forth with the server). It would be more than a little painful and hopefully avoidable.
Based on A. Rodas's answer below, I came up with the following:
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
Unit testing of Tkinter code is not an easy issue. For instance, the IDLE does not have a proper test suite, even though it is part of the standard library. Since you mention that this is going to be the only use of Tkinter in your application, I'd suggest to make unit tests for the outcome of this code: the value of filename
.
For instance, you can have a test for a .csv file, and another one for an incorrect file extension. Since tkFileDialog
returns an empty string if it is closed by the user, add also a test where 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'
# ...
You could just patch the calls to tkinter: patch tk.Tk() because most CI's will error because they don't have displays. Also patch the file dialog so you can simulate return values and that it is being called with what you expect.
@patch('your_module.tk.Tk')
def test_your_stuff(self, Tk)
with @patch('your_module.tkFileDialog.askopenfilename') as file_dialog:
expected = 'expected return value'
assert expected = your_function_calling_file_dialog()
file_dialog.assert_called_once_with(whatever, you, expect, it, to, be, called, with)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With