Running a test on the Event Dispatch Thread

317 views
Skip to first unread message

Bruce Alspaugh

unread,
Jan 15, 2010, 2:00:31 PM1/15/10
to testng-users
Does TestNG provide a way to tell the test runner that you would like
to run a test method on a particular thread? This becomes important
when testing AWT, Swing, and SWT code because the components must be
created and accessed on the Event Dispatch Thread.

For example, it would be really nice if I could specify a
java.util.concurrent.Executor to run the test method on in the test
annotation. For example:

@Test(executor=SwingExecutor.class)
public void testMyComponentOnTheEDT() throws Exception {
// this test code is executed on the EDT
}

The test runner could submit a FutureTask that runs the test method to
the Executor specified in the annotation. The test runner would wait
for the test method to finish running to see if it throws an
exception. If it throws an exception, it would be re-thrown back to
the original test runner thread. You could have different Executor
implementations that run tasks on the Swing EDT, the SWT EDT, a thread
pool, or any implementation of java.util.concurrent.Executor.

Cédric Beust ♔

unread,
Jan 15, 2010, 3:21:42 PM1/15/10
to testng...@googlegroups.com
Hi Bruce,

Why not simply call SwingUtilities#invokeLater in your test method?

--
Cedric


--
You received this message because you are subscribed to the Google Groups "testng-users" group.
To post to this group, send email to testng...@googlegroups.com.
To unsubscribe from this group, send email to testng-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/testng-users?hl=en.






--
Cédric


Alex Ruiz

unread,
Jan 15, 2010, 3:31:39 PM1/15/10
to testng...@googlegroups.com
Hi Cedric,

with invokeLater the test thread will never know about exceptions thrown in the EDT.

Bruce, you can do the same with FEST's GuiActionRunner (please see http://alexruiz.developerblogs.com/?p=160 ) After replying to your comment on my blog, I realized that a SwingExecutor would not be necessary if you use GuiActionRunner

Cheers,
-Alex

2010/1/15 Cédric Beust ♔ <cbe...@google.com>

Bruce Alspaugh

unread,
Jan 15, 2010, 6:20:24 PM1/15/10
to testng-users
Hi Cedric and Alex,

I've been using a utility class similar to FEST's GuiActionRunner:

@Test
public void testMyComponent() throws Exception {
EDTUtils.submitLater(this, "doTestMyComponent");
}

public void doTestMyComponent() throws WhateverException {
// This code runs in the EDT
}

Internally, the submitLater method creates a FutureTask that uses
reflection to run the specified method. The FutureTask is submitted
to an Executor that uses SwingUtilities#submitLater to run the
FutureTask on the EDT. It then calls FutureTask#get to wait for the
task to complete, and either retrieve the optional return value or
rethrow the WhateverException back onto the test runner thread. The
doTestMyComponent method could optionally return a value which would
be returned by submitLater. The submitLater method can also take an
optional var-args array of parameters to pass into
doTestMyComponent.

If I could somehow configure the test runner as I originally
suggested, I think it would be cleaner. I would not have to write two
separate methods, not have to use reflection or inner classes to
invoke doTestMyComponent, and be a bit more self-documenting because I
could specify the WhateverException in the annotated test method
rather than an arbitrary Exception.

Thanks for the quick replies,

Bruce

On Jan 15, 2:31 pm, Alex Ruiz <alex.ruiz...@gmail.com> wrote:
> Hi Cedric,
>
> with invokeLater the test thread will never know about exceptions thrown in
> the EDT.
>

> Bruce, you can do the same with FEST's GuiActionRunner (please seehttp://alexruiz.developerblogs.com/?p=160) After replying to your comment


> on my blog, I realized that a SwingExecutor would not be necessary if you
> use GuiActionRunner
>
> Cheers,
> -Alex
>
> 2010/1/15 Cédric Beust ♔ <cbe...@google.com>
>
> > Hi Bruce,
>
> > Why not simply call SwingUtilities#invokeLater in your test method?
>
> > --
> > Cedric
>

> > On Fri, Jan 15, 2010 at 11:00 AM, Bruce Alspaugh <alspau...@gmail.com>wrote:
>
> >> Does TestNG provide a way to tell the test runner that you would like
> >> to run a test method on a particular thread?  This becomes important
> >> when testing AWT, Swing, and SWT code because the components must be
> >> created and accessed on the Event Dispatch Thread.
>
> >> For example, it would be really nice if I could specify a
> >> java.util.concurrent.Executor to run the test method on in the test
> >> annotation.  For example:
>
> >> @Test(executor=SwingExecutor.class)
> >> public void testMyComponentOnTheEDT() throws Exception {
> >>  // this test code is executed on the EDT
> >> }
>
> >> The test runner could submit a FutureTask that runs the test method to
> >> the Executor specified in the annotation. The test runner would wait
> >> for the test method to finish running to see if it throws an
> >> exception.  If it throws an exception, it would be re-thrown back to
> >> the original test runner thread.  You could have different Executor
> >> implementations that run tasks on the Swing EDT, the SWT EDT, a thread
> >> pool, or any implementation of java.util.concurrent.Executor.
>
> >> --
> >> You received this message because you are subscribed to the Google Groups
> >> "testng-users" group.
> >> To post to this group, send email to testng...@googlegroups.com.
> >> To unsubscribe from this group, send email to

> >> testng-users...@googlegroups.com<testng-users%2Bunsu...@googlegroups.com>


> >> .
> >> For more options, visit this group at
> >>http://groups.google.com/group/testng-users?hl=en.
>
> > --

> > ***Cédric
> > *


>
> > --
> > You received this message because you are subscribed to the Google Groups
> > "testng-users" group.
> > To post to this group, send email to testng...@googlegroups.com.
> > To unsubscribe from this group, send email to

> > testng-users...@googlegroups.com<testng-users%2Bunsu...@googlegroups.com>

Bruce Alspaugh

unread,
Jan 15, 2010, 5:12:58 PM1/15/10
to testng...@googlegroups.com
Hi Cedric and Alex,

Thanks for the quick replies.  It is possible to get an exception thrown in the EDT with SwingUtilities#invokeLater if you pass it a FutureTask and then call the get() method of the FutureTask.  Or you can use SwingUtilities#invokeAndWait.  I was thinking that by specifying an arbitrary Executor that a test method runs on, it would be a much more general solution than just testing GUI code.  You can specify thread pools or anything else you want. A FutureTask would work with any arbitrary Executor.

I just recently discovered FEST and TestNG, and I'll have to study them.  What I have been doing with JUnit 4 is using a utility class that is similar to the FEST GuiActionRunner so my tests look like this:

@Test
public void testMethod() throws Exception {
    EDTUtils.submitLater(this, "doTestMethod");
}

public void doTestMethod() throws WhateverException {
    // this code runs in the EDT
}

Basically, the EDTUtils#submitLater method creates a FutureTask that uses reflection to call the named method of the specified object.  The FutureTask is submitted to an Executor that runs the task on the EDT.  The submitLater method then calls FutureTask#get to wait for the test method to finish and retrieve any return value from the test method or rethrow any exception originally thrown by the test method.  I can use either SwingUtilities#invokeLater or SwingUtilities#invokeAndWait to implement the Executor.  The EDTUtils.submitLater method can also take an optional var-args array of parameters to pass to the invoked test method.  The test method could optionally return a value which is returned by EDTUtils#submitLater.  My original version let me just submit a Callable, rather than use reflection but it was a bit awkward because I had to keep implementing that interface.  I kept using an anonymous inner class to implement Callable, but didn't like the nesting.  Maybe closures will make this cleaner someday.

I was hoping TestNG might be a bit more configurable than JUnit 4 so I would not have to write two methods and avoid the need for inner classes or reflection. Specifying test methods inside strings is not very refactor-friendly if I use my IDE to rename the test method.  I also would like to avoid all the nesting involved with inner classes.  It would also be a bit more self-documenting because the annotated method could then throw something more specific than a generic Exception.

Bruce
Reply all
Reply to author
Forward
0 new messages