Multiple ui-tests in one TestClass

WindowTester allows you to easily create and run unit tests for every GUI they build. It can also be used to generate system level tests.

Moderators: gnebling, Eric Clayberg, Dan Rubel, keertip, Phil Quitslund

Multiple ui-tests in one TestClass

Postby mseele » Wed Jan 23, 2008 5:01 am

Hi,

is it possible to run multilple ui-tests in one TestClass? I'm always getting a SWTException if i do this. Here's the exception:

Code: Select all
org.eclipse.swt.SWTException: Device is disposed
   at org.eclipse.swt.SWT.error(Unknown Source)
   at org.eclipse.swt.SWT.error(Unknown Source)
   at org.eclipse.swt.SWT.error(Unknown Source)
   at org.eclipse.swt.widgets.Display.error(Unknown Source)
   at org.eclipse.swt.widgets.Display.syncExec(Unknown Source)
   at com.windowtester.runtime.swt.internal.state.MenuWatcher.startWatching(MenuWatcher.java:63)
   at com.windowtester.runtime.swt.internal.UIContextSWT.setDisplay(UIContextSWT.java:201)
   at com.windowtester.swt.UIContextFactory.createContext(UIContextFactory.java:36)
   at com.windowtester.swt.UIContextFactory.createContext(UIContextFactory.java:23)
   at junit.extensions.swt.ExecutionEnvironment.createUI(ExecutionEnvironment.java:92)
   at junit.extensions.swt.ExecutionEnvironment.getUI(ExecutionEnvironment.java:80)
   at junit.extensions.swt.SWTExecutionMonitor.getUI(SWTExecutionMonitor.java:185)
   at junit.extensions.swt.SWTExecutionContext.getUI(SWTExecutionContext.java:36)
   at junit.extensions.UITestCaseCommon.getUI(UITestCaseCommon.java:259)
   at de.wt.TestSnippet63.testCancel(TestSnippet63.java:25)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   at java.lang.reflect.Method.invoke(Method.java:585)
   at junit.framework.TestCase.runTest(TestCase.java:164)
   at junit.framework.TestCase.runBare(TestCase.java:130)
   at junit.extensions.UITestCaseCommon.access$101(UITestCaseCommon.java:26)
   at junit.extensions.UITestCaseCommon$1.run(UITestCaseCommon.java:140)
   at junit.extensions.core.SequenceRunner$1.run(SequenceRunner.java:44)


I use following two code-sections as test. The first one is the Application and the second one the TestClass.

Thanks
mseele

Code: Select all
package de.wt;

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;

public class Snippet63 {

   public static void main(String[] args) {
      Display display = Display.getDefault();
      System.out.println(display + " " + Thread.currentThread());
      Shell shell = new Shell(display);
      shell.setText("dialog");
      shell.pack();
      shell.open();
      final boolean[] result = new boolean[1];
      final Shell dialog = new Shell(shell, SWT.DIALOG_TRIM
            | SWT.APPLICATION_MODAL);
      dialog.setText("promt");
      dialog.setLayout(new RowLayout());
      final Button ok = new Button(dialog, SWT.PUSH);
      ok.setText("OK");
      Button cancel = new Button(dialog, SWT.PUSH);
      cancel.setText("Cancel");
      Listener listener = new Listener() {
         public void handleEvent(Event event) {
            result[0] = event.widget == ok;
            dialog.close();
         }
      };
      ok.addListener(SWT.Selection, listener);
      cancel.addListener(SWT.Selection, listener);
      dialog.pack();
      dialog.open();
      System.out.println("Prompt ...");
      while (!dialog.isDisposed()) {
         if (!display.readAndDispatch())
            display.sleep();
      }
      System.out.println("Result: " + result[0]);
      while (!shell.isDisposed()) {
         if (!display.readAndDispatch()) {
            display.sleep();
         }
      }
      display.dispose();
      System.out.println("Exit");
   }

}


Code: Select all
package de.wt;

import junit.extensions.UITestCaseSWT;

import com.windowtester.runtime.IUIContext;
import com.windowtester.runtime.swt.locator.ButtonLocator;
import com.windowtester.runtime.swt.locator.ShellLocator;

public class TestSnippet63 extends UITestCaseSWT {

   /**
    * Create an Instance
    */
   public TestSnippet63() {
      super(Snippet63.class);
   }

   public void testOk() throws Exception {
      IUIContext ui = getUI();
      ui.click(new ButtonLocator("OK"));
      ui.close(new ShellLocator("dialog", false));
   }

   public void testCancel() throws Exception {
      IUIContext ui = getUI();
      ui.click(new ButtonLocator("Cancel"));
      ui.close(new ShellLocator("dialog", false));
   }

}
mseele
 
Posts: 4
Joined: Wed Jan 23, 2008 12:57 am

Re: Multiple ui-tests in one TestClass

Postby gnebling » Wed Jan 23, 2008 12:27 pm

See this post if this is what you're looking for:
viewtopic.php?f=5&t=933
gnebling
Moderator
 
Posts: 243
Joined: Tue Aug 22, 2006 7:49 am

Re: Multiple ui-tests in one TestClass

Postby mseele » Thu Jan 24, 2008 3:49 am

I Got the same error if i do it with a TestSuite.

Code: Select all
org.eclipse.swt.SWTException: Device is disposed
   at org.eclipse.swt.SWT.error(Unknown Source)
   at org.eclipse.swt.SWT.error(Unknown Source)
   at org.eclipse.swt.SWT.error(Unknown Source)
   at org.eclipse.swt.widgets.Display.error(Unknown Source)
   at org.eclipse.swt.widgets.Display.syncExec(Unknown Source)
   at com.windowtester.runtime.swt.internal.state.MenuWatcher.startWatching(MenuWatcher.java:63)
   at com.windowtester.runtime.swt.internal.UIContextSWT.setDisplay(UIContextSWT.java:201)
   at com.windowtester.swt.UIContextFactory.createContext(UIContextFactory.java:36)
   at com.windowtester.swt.UIContextFactory.createContext(UIContextFactory.java:23)
   at junit.extensions.swt.ExecutionEnvironment.createUI(ExecutionEnvironment.java:92)
   at junit.extensions.swt.ExecutionEnvironment.getUI(ExecutionEnvironment.java:80)
   at junit.extensions.swt.SWTExecutionMonitor.getUI(SWTExecutionMonitor.java:185)
   at junit.extensions.swt.SWTExecutionContext.getUI(SWTExecutionContext.java:36)
   at junit.extensions.UITestCaseCommon.getUI(UITestCaseCommon.java:259)
   at de.wt.Test2Snippet63.testCancel(Test2Snippet63.java:19)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   at java.lang.reflect.Method.invoke(Method.java:585)
   at junit.framework.TestCase.runTest(TestCase.java:164)
   at junit.framework.TestCase.runBare(TestCase.java:130)
   at junit.extensions.UITestCaseCommon.access$101(UITestCaseCommon.java:26)
   at junit.extensions.UITestCaseCommon$1.run(UITestCaseCommon.java:140)
   at junit.extensions.core.SequenceRunner$1.run(SequenceRunner.java:44)


Please test my Snippet! Should i send you a bugreport per mail?

Snippet63.java
Code: Select all
package de.wt;

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;

public class Snippet63 {

   public static void main(String[] args) {
      Display display = Display.getDefault();
      System.out.println(display + " " + Thread.currentThread());
      Shell shell = new Shell(display);
      shell.setText("dialog");
      shell.pack();
      shell.open();
      final boolean[] result = new boolean[1];
      final Shell dialog = new Shell(shell, SWT.DIALOG_TRIM
            | SWT.APPLICATION_MODAL);
      dialog.setText("promt");
      dialog.setLayout(new RowLayout());
      final Button ok = new Button(dialog, SWT.PUSH);
      ok.setText("OK");
      Button cancel = new Button(dialog, SWT.PUSH);
      cancel.setText("Cancel");
      Listener listener = new Listener() {
         public void handleEvent(Event event) {
            result[0] = event.widget == ok;
            dialog.close();
         }
      };
      ok.addListener(SWT.Selection, listener);
      cancel.addListener(SWT.Selection, listener);
      dialog.pack();
      dialog.open();
      System.out.println("Prompt ...");
      while (!dialog.isDisposed()) {
         if (!display.readAndDispatch())
            display.sleep();
      }
      System.out.println("Result: " + result[0]);
      while (!shell.isDisposed()) {
         if (!display.readAndDispatch()) {
            display.sleep();
         }
      }
      display.dispose();
      System.out.println("Exit");

      System.err.println(visit(Thread.currentThread().getThreadGroup()));
   }

}


TestSuiteSnippet63.java
Code: Select all
package de.wt;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

public class TestSuiteSnippet63 extends TestCase {

   public static Test suite() {
      TestSuite suite = new TestSuite();
      suite.addTestSuite(Test1Snippet63.class);
      suite.addTestSuite(Test2Snippet63.class);
      return suite;
   }

}


Test1Snippet63.java
Code: Select all
package de.wt;

import junit.extensions.UITestCaseSWT;

import com.windowtester.runtime.IUIContext;
import com.windowtester.runtime.swt.locator.ButtonLocator;
import com.windowtester.runtime.swt.locator.ShellLocator;

public class Test1Snippet63 extends UITestCaseSWT {

   /**
    * Create an Instance
    */
   public Test1Snippet63() {
      super(Snippet63.class);
   }

   public void testOk() throws Exception {
      IUIContext ui = getUI();
      ui.click(new ButtonLocator("OK"));
      ui.close(new ShellLocator("dialog", false));
   }

}


Test2Snippet63.java
Code: Select all
package de.wt;

import junit.extensions.UITestCaseSWT;

import com.windowtester.runtime.IUIContext;
import com.windowtester.runtime.swt.locator.ButtonLocator;
import com.windowtester.runtime.swt.locator.ShellLocator;

public class Test2Snippet63 extends UITestCaseSWT {

   /**
    * Create an Instance
    */
   public Test2Snippet63() {
      super(Snippet63.class);
   }

   public void testCancel() throws Exception {
      IUIContext ui = getUI();
      ui.click(new ButtonLocator("Cancel"));
      ui.close(new ShellLocator("dialog", false));
   }

}
Last edited by mseele on Fri Jan 25, 2008 12:50 am, edited 1 time in total.
mseele
 
Posts: 4
Joined: Wed Jan 23, 2008 12:57 am

Re: Multiple ui-tests in one TestClass

Postby gnebling » Thu Jan 24, 2008 8:18 am

I tried your tests individually and as a testsuite and it worked fine.
Can you run your tests individually? What version of Eclipse are you using to run the tests?
Make sure to run the tests as JUnit Tests and not JUnit Plugin Tests.
Try the latest WindowTester build if you're not already using the latest.
gnebling
Moderator
 
Posts: 243
Joined: Tue Aug 22, 2006 7:49 am

Re: Multiple ui-tests in one TestClass

Postby mseele » Fri Jan 25, 2008 12:23 am

Yes i can run my tests individualy. We're using Eclipse SDK 3.3.1.1 under Windows XP (the exception also appears under Linux).
WindowTester version is 3.2.0 (the exception also appears with 3.2.1).
The tests are run as JUnit Tests and not as JUnit Plugin Tests.

Could you provide you're workspace that we can check what's different to ours?
mseele
 
Posts: 4
Joined: Wed Jan 23, 2008 12:57 am

Re: Multiple ui-tests in one TestClass

Postby gnebling » Fri Jan 25, 2008 9:48 am

My bad, it was failing on mine too and it's because the dialog has already been closed/disposed when testOK() ran so testCancel() couldn't find the dialog.
If you comment this line ui.close(new ShellLocator("dialog", false)); in testOK() it should be fine.
gnebling
Moderator
 
Posts: 243
Joined: Tue Aug 22, 2006 7:49 am

Re: Multiple ui-tests in one TestClass

Postby mseele » Sun Jan 27, 2008 11:19 pm

But if i have to comment out the close line, you're toolkit is unusable. To test a big application, you have to "restart" the application in every test/most of the tests. If you want to test the error handling and the application will be closed if an special error occurs, for example.
So it is not possible to "restart" the application in every single test and run them all as a test suite?
mseele
 
Posts: 4
Joined: Wed Jan 23, 2008 12:57 am

Re: Multiple ui-tests in one TestClass

Postby Mac » Mon Jan 28, 2008 8:56 am

Hi mseele,

no that is not possible.
Your application should be able to react on errors without requiring a restart.
We are successfully using WindowTester with our application and have 106 independant Tests running.

All we did is to derive a "TestBasis" class from "UITestCaseSWT" and used the "setUp" and "tearDown" methods to ensure
that the application offers the same starting conditions for every test case.
This way you can develope your test cases individually and still run them all together in a huge suite.

bye,

Mac
Mac
 
Posts: 14
Joined: Thu Apr 05, 2007 4:19 am

Re: Multiple ui-tests in one TestClass

Postby vcycyv » Mon Apr 07, 2008 1:57 am

Hi Mac,(or anyone will answer my question)

If I have multiple junit test cases, each one ends with ui.close(), how can I add these Junit cases into one TestSuite? Because if the first junit test case calls ui.close(), the the second test case won't start up GUI. Mac says setup(),teardown() may solve this ,but how to? will any one provide an example? My cases are like below:
Demo.java
Code: Select all
public class Demo extends UITestCaseSWT {
           public void testDemo() throws Exception {
              IUIContext ui = getUI();
              ui.click("file/New Contact..."));
              ui.wait(new ShellShowingCondition(""));
              ui.enterText("1");
              ui.keyClick(WT.TAB);
              ui.enterText("2");
              ui.click(new LabeledTextLocator("Street"));
              ui.click(new ButtonLocator("&Finish"));
              ui.close(new SWTWidgetLocator(Shell.class, "RCP Contacts Editor"));
              ui.wait(new ShellDisposedCondition("RCP Contacts Editor"));
                 }
        }

Demo2.java
Code: Select all
public class Demo2 extends UITestCaseSWT {
           public void testDemo() throws Exception {
              IUIContext ui = getUI();
              ui.click("file/New Contact..."));
              ui.wait(new ShellShowingCondition(""));
              ui.enterText("3");
              ui.keyClick(WT.TAB);
              ui.enterText("4");
              ui.click(new LabeledTextLocator("Street"));
              ui.click(new ButtonLocator("&Finish"));
              ui.close(new SWTWidgetLocator(Shell.class, "RCP Contacts Editor"));
              ui.wait(new ShellDisposedCondition("RCP Contacts Editor"));
                 }


MyTestSuite.java
public class MyTestSuite extends TestCase
{
public static Test suite()
{
TestSuite suite = new TestSuite();
suite.addTestSuite(Demo.class);
suite.addTestSuite(Demo2.class);
return suite;
}
}
will anyone give an example how to apply setup(),teardown() for this case?
vcycyv
 
Posts: 2
Joined: Mon Mar 31, 2008 10:19 pm

Re: Multiple ui-tests in one TestClass

Postby Phil Quitslund » Tue Apr 08, 2008 10:49 am

Here's one way we do this in our tests.

We use a base class that defines some convenience methods and does test lifecycle management:

Code: Select all
import org.eclipse.swt.widgets.Display;

import com.windowtester.runtime.swt.UITestCaseSWT;

public class AbstractTest extends UITestCaseSWT {

   
   
   /** Made final to avoid accidental overrides.
    * @see junit.framework.TestCase#setUp()
    */
   @Override
   protected final void setUp() throws Exception {
      Display.getDefault().asyncExec(new Runnable() {
         public void run() {
            uiSetup();
         }         
      });
   }
   
   
   /** Made final to avoid accidental overrides.
    * @see junit.framework.TestCase#tearDown()
    */
   @Override
   protected final void tearDown() throws Exception {
      Display.getDefault().syncExec(new Runnable() {
         public void run() {
            uiTearDown();
         }         
      });
   }
   
   
   /**
    * Set up the test fixture --- will be run on the UI thread.
    */
   public void uiSetup() {
      //
   }
   
   
   /**
    * Set up the test fixture --- will be run on the UI thread.
    */
   public void uiTearDown() {
      //
   }
}


Tests can subclass this and define test-specifc ui set and teardown logic like so:

Code: Select all
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

import com.windowtester.runtime.IUIContext;
import com.windowtester.runtime.swt.condition.shell.ShellDisposedCondition;
import com.windowtester.runtime.swt.condition.shell.ShellShowingCondition;
import com.windowtester.runtime.swt.locator.ButtonLocator;
import com.windowtester.runtime.swt.locator.jface.DialogMessageLocator;

public class DemoTest extends AbstractTest {

   
   @Override
   public void uiSetup() {
      MessageDialog.openInformation(new Shell(Display.getDefault()), "Info", "Something");
   }
   
   public void testAssertText() throws Exception {
      IUIContext ui = getUI();
      ui.wait(new ShellShowingCondition("Info"));
      ui.assertThat(new DialogMessageLocator().hasText("Something"));
      ui.click(new ButtonLocator("OK"));
      ui.wait(new ShellDisposedCondition("Info"));
   }
   
   public void uiTearDown() {
      //nothing to do...  (but your close would go here)
   }
   
}


A suite looks like this:

Code: Select all
import junit.framework.Test;
import junit.framework.TestSuite;

public class DemoSuite {

   public static Test suite() {
      TestSuite suite = new TestSuite(
            "Demo Test Suite");
      //$JUnit-BEGIN$
      suite.addTestSuite(DemoTest.class);
      suite.addTestSuite(DemoTest.class);
      //$JUnit-END$
      return suite;
   }

}


Hope this helps!
--
Phil Quitslund
Software Engineer
Google, Inc.
Phil Quitslund
Moderator
 
Posts: 491
Joined: Fri Apr 28, 2006 6:26 am

Re: Multiple ui-tests in one TestClass

Postby Mac » Tue Apr 22, 2008 1:07 am

Hi vcycyv,

What Phil explained is just what I meant.

Remove these lines from your Demo.class testcase and all other test cases:


ui.close(new SWTWidgetLocator(Shell.class, "RCP Contacts Editor"));
ui.wait(new ShellDisposedCondition("RCP Contacts Editor"));


Maybe it is generally usefull to stop recording before closing the application.
The WindoesTester Framework will close your application after all test have finished!
Mac
 
Posts: 14
Joined: Thu Apr 05, 2007 4:19 am

Re: Multiple ui-tests in one TestClass

Postby Phil Quitslund » Tue Apr 22, 2008 8:54 am

Mac is right: the explicit calls to close are unnecessary (and in this case dangerous!) In fact, this conversation has convinced me to revisit earlier proposals to elide those sorts of lines from the recorded test...

Thanks for all of your input!
--
Phil Quitslund
Software Engineer
Google, Inc.
Phil Quitslund
Moderator
 
Posts: 491
Joined: Fri Apr 28, 2006 6:26 am


Return to Window Tester

Who is online

Users browsing this forum: No registered users and 1 guest