Note that there are some explanatory texts on larger screens.

plurals
  1. POUnittest Tkinter File Dialog
    primarykey
    data
    text
    <h1>Question</h1> <p>Is there any way to automate a <code>tkFileDialog</code> selection to run it through <code>unittest</code>? The following is the only use of <code>tkinter</code> in my application:</p> <pre><code>root = Tkinter.Tk() types = [('Comma Separated Values', '.csv'), ('All Files', '*')] filename = tkFileDialog.askopenfilename(parent=root, filetypes=types) root.destroy() </code></pre> <p><strong>Edit</strong>: I didn't mention that this part of the code was trapped in a method call from a class outside my control. <hr></p> <h1>Background</h1> <p>I've built a local app that creates an http server on <code>localhost</code> 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 <code>Tcl/Tk</code>.</p> <h2>Attempt #1</h2> <p>If I could get to the underlying widgets, I could generate the clicks like in <a href="https://stackoverflow.com/questions/6167019/generate-a-click-event-in-tkinter">this question</a>. However, looking at the <a href="http://hg.python.org/cpython/file/5accb0ac8bfb/Lib/lib-tk/tkCommonDialog.py" rel="nofollow noreferrer">dialog source</a>, it appears to me that the <code>Tcl</code> call in lines 48-50 is blocking. Is this a correct assumption?</p> <h2>Attempt #2</h2> <p>I thought there might be a way using <code>Tcl</code> commands directly through <code>root.tk.call</code>. Since I'm on <code>Python2</code>, I think the underlying <code>Tcl</code> is a single call to <code>tk_getOpenFile</code>. Would I have to ensure the <code>Tcl</code> interpreter is threaded? Is there any <code>Tcl/Tk</code> command that can help me out here?</p> <h2>Attempt #3</h2> <p>I could implement the file selection from scratch using <code>os.listdir</code> 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.</p> <p><hr></p> <h1>Solution</h1> <p>Based on A. Rodas's answer below, I came up with the following:</p> <pre><code>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 </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload