Question

Which is better to use and why in case of automating the test cases of a TCL/TK GUI based application:

BUTTON invoke

Or

event generate BUTTON <ButtonPress-1>

and the same command with button release

Was it helpful?

Solution 2

Well, what they test is nearly but not quite entirely the same. In the first case you can test the button's command (or whether it's disabled or not) without touching the event system. In the second case you test whether the button behaves as it should given an event (which should include invoking the command after you've generated a press and a release).

(ETA: and an Enter event before that as Donal notes in his answer. Sorry I missed that. Also, as I believe he is saying, default bindings don't really need to be tested. The main point of my answer was to discuss "top-down" versus "bottom-up" approaches to selecting test cases.)

If you're being an optimist, you would test by generating events. If you get a successful command invocation after generating the events, all is well. However, if the test fails, you can't be sure which part of the chain failed: the binding, the setting of the command option, the command itself, the state of the button, and so on.

If you're being a pessimist, you would test every link in the chain separately by getting the command option value and invoking it directly, calling invoke on the button, generating the events, and possibly more. If all those tests are successful, all is well, just like above. If any of them fails, you will immediately know what needs to be fixed.

The best strategy is probably achieved by compromise: start with "abstract" testing (in this case, generating events), and add detailed testing if you start having trouble somewhere. Having dozens of tests that just confirm that everything is OK seems impressive but doesn't really add much except inertia which you will have to deal with if the specifications change.

OTHER TIPS

Usually, when testing a Tk button in an application it is quite enough to test by just calling the invoke method (or even by calling a procedure that the registered -command invokes). You shouldn't normally try to test Tk itself (it has its own test suite) because then you are just entangling your tests with libraries that you don't entirely control. This particularly applies when it comes to unit tests; those should check just the code that you have written (e.g., code that is invoked by the button in response to it being invoked) and not how that came to happen.

But there are times when you should also do larger integration tests so as to ensure that you aren't running into problems with things that only show up when you stick things together. You just need to be aware that integration testing is much more complex. For example, to generate a button click correctly, you also need to generate the (simulated) mouse movements so that the click is generated when the mouse is over the button (because Tk buttons only arm themselves to deal with mouse clicks when the mouse is over them, and find that out via <Enter> and <Leave> events; it's a subtle effect, but important). Sounds simple, but it's hard to get right. It's even harder to get right across platforms (font sizes change, window management policies change, etc.) I'm not saying “Don't do integration tests”. I'm just saying that they're really awkward.

And none of this precludes doing user acceptance testing. That's important with GUI apps as they are always things that are (well, should be) designed to have users interacting with them; that's their point. Doing one type of testing doesn't mean you don't need to do the other higher-level types of testing; it just should make it easier for the higher-level tests to pass…


If you're using event generate to trigger a button, you'll need to create an <Enter>, a <ButtonPress-1> and a <ButtonRelease-1>, in that order.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top