Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "RapUITesting"

(completed page)
(24 intermediate revisions by 8 users not shown)
Line 1: Line 1:
 
| [[RAP|RAP wiki home]] | [http://eclipse.org/rap RAP project home] |
 
| [[RAP|RAP wiki home]] | [http://eclipse.org/rap RAP project home] |
 +
 +
===THIS IS EXPERIMENTAL! WE MAKE OUR RESEARCH RESULTS AVAILABLE TO ENABLE FEEDBACK===
 +
 +
 
===Writing UI Tests for RAP applications===
 
===Writing UI Tests for RAP applications===
  
This document will describe '''one''' way how to do UI tests for you [[RAP]] applications. For this way, we use the combination of JUnit, [http://openqa.org/selenium/ Selenium] and [http://openqa.org/selenium-rc Selenium RC] to have automatic UI tests which can be integrated into your JUnit testsuite.
+
This document will describe '''one possible''' way to do UI tests for [[RAP]] applications. With this approach we use the combination of JUnit, [http://openqa.org/selenium/ Selenium] and [http://openqa.org/selenium-rc Selenium RC] to have automated UI tests which can be integrated into your JUnit testsuite.
  
We will provide a simple example application to demonstrate the usage of the several tools.
+
Below is a simple example application to demonstrate the usage of the tool chain.
  
 
==Requirements==
 
==Requirements==
 
If you don't have it, you need at least these files in order to follow the tutorial:
 
If you don't have it, you need at least these files in order to follow the tutorial:
* [http://release.openqa.org/selenium-remote-control/nightly/selenium-remote-control-0.9.1-SNAPSHOT.zip Selenium Remote Control 0.9.1]
+
* [http://seleniumhq.org/download/ Selenium Core & Remote Control]
* [http://wiki.openqa.org/download/attachments/1736/qooxdooExtension_0_2.zip?version=1 Selenium User Extension for Qooxdoo]
+
* [https://qooxdoo-contrib.svn.sourceforge.net/svnroot/qooxdoo-contrib/trunk/qooxdoo-contrib/Simulator/0.1/tool/selenium/user_extension/user-extensions-qooxdoo.js Qooxdoo Simulator (Selenium Extension)]
  
 
Extract these files in a directory of your choice.
 
Extract these files in a directory of your choice.
Line 16: Line 20:
 
First we need something to test. Therefor I put together a little example application to demonstrate the UI testing approach.
 
First we need something to test. Therefor I put together a little example application to demonstrate the UI testing approach.
  
Just create a new plugin project, add <code>org.eclipse.rap.ui.workbench</code> as a dependency and create the following class:
+
Just create a new plugin project, add <code>org.eclipse.rap.ui.workbench</code> as a dependency, also add all the needed dependency to avoid errors, and create the following class:
 
<pre>
 
<pre>
 
package org.eclipse.rap.demo.ui.tests;
 
package org.eclipse.rap.demo.ui.tests;
Line 32: Line 36:
 
public class TestApp implements IEntryPoint {
 
public class TestApp implements IEntryPoint {
  
public Display createUI() {
+
  public int createUI() {
Display d = new Display();
+
    Display d = new Display();
final Shell s = new Shell(d, SWT.SHELL_TRIM);
+
    final Shell s = new Shell(d, SWT.SHELL_TRIM);
s.setLayout(new GridLayout());
+
    s.setLayout(new GridLayout());
s.setText("App Title");
+
    s.setText("App Title");
final Button b1 = new Button(s, SWT.PUSH);
+
    final Button b1 = new Button(s, SWT.PUSH);
b1.setText("Before");
+
    b1.setText("Before");
b1.addSelectionListener(new SelectionAdapter() {
+
    b1.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
+
      public void widgetSelected(SelectionEvent e) {
MessageDialog.openInformation(s, "MessageBox",
+
        MessageDialog.openInformation(s,  
"Changing the button text now...", null);
+
                                      "MessageBox",
b1.setText("After");
+
                              "Changing the button text now...");
}
+
b1.setText("After");
});
+
      }
s.pack();
+
    } );
s.open();
+
    b1.setData( WidgetUtil.CUSTOM_WIDGET_ID, "myButton" );
return d;
+
    s.pack();
}
+
    s.open();
 +
    while (!s.isDisposed()) {
 +
if (!d.readAndDispatch())
 +
d.sleep();
 +
    }
 +
    return 0;
 +
  }
  
 
}
 
}
 
</pre>
 
</pre>
  
As you can see, this is a really tiny RAP example - but big enough to be worth to test it.
+
WARNING: this code is not complete, it's a snippet, you will have to realize the Activator class and entry point configuration.
 +
As you can see, this is a really tiny RAP example - but big enough to be worth to test it.  
  
==Preparing the tests==
 
Now create a new java project and add the JUnit library. Additionally, you need to add the <code>selenium-java-client-driver.jar</code> to your project in order to use the Selenium Remote Control.
 
  
As RAP applications have a little bit other nature than normal web applications, we need to work around some techniques of selenium. First, you can use commands like <code>click</code> against a target element on your page. The target defined as in <code>id</code> element of your (x)html source. As Qooxdoo doesn't provide ids for their widgets, we need the mentioned [http://wiki.openqa.org/display/SEL/qooxdooExtension Selenium User Extension for Qooxdoo]. With this, all targets prefixed with "qx=" will now use another "find-the-target" algorithm based on <code>UserData</code> provided by Qooxdoo widgets.
+
At the moment, all widget ids are looking like "w1", "w2", "w3". As these ids are generated in the order the widgets are created, it isn't a very good way to handle it. Imagine: You wrote hundred of testcases and then you see: Ah, my application needs an additional label somewhere, all the widgets created after this label have another ID.  
 +
That's why we use WidgetUtil.CUSTOM_WIDGET_ID as key for custom widget data. This way we can easily set a human-readable name for each of the widgets under test.
  
As we have an internal identifier for each widget in RAP which is known by the server and the client side, we can use this to put it into the UserData field. Apply the following patch to the <code>org.eclipse.rap.rwt</code> component in order to have the <code>UserData</code>:
+
== Starting the app ==
 +
Besides adding the extension for the new entrypoint is it registered there is one important thing to do. We need to activate the UI Test mode in order to get several advantages during running the tests. Just add ''-Dorg.eclipse.rwt.enableUITests=true'' as VM argument to your launch configuration.
  
<pre>
+
'''Note:''' The VM argument has been renamed in RAP 2.0 to ''-Dorg.eclipse.rap.rwt.enableUITests''.
### Eclipse Workspace Patch 1.0
+
#P org.eclipse.rap.rwt
+
Index: src/org/eclipse/swt/lifecycle/ControlLCAUtil.java
+
===================================================================
+
RCS file: /cvsroot/technology/org.eclipse.rap/org.eclipse.rap.rwt/src/org/eclipse/swt/lifecycle/ControlLCAUtil.java,v
+
retrieving revision 1.1
+
diff -u -r1.1 ControlLCAUtil.java
+
--- src/org/eclipse/swt/lifecycle/ControlLCAUtil.java 26 Apr 2007 06:46:37 -0000 1.1
+
+++ src/org/eclipse/swt/lifecycle/ControlLCAUtil.java 29 May 2007 16:21:01 -0000
+
@@ -94,6 +94,12 @@
+
    }
+
  }
+
 
+
+  public static void writeUserData(final Control control) throws IOException {
+
+ JSWriter writer = JSWriter.getWriterFor(control);
+
+ String newValue = WidgetUtil.getId( control );
+
+ writer.set("UserData", new String[] {newValue, "selenium"});
+
+ }
+
+
  // TODO [rh] there seems to be a qooxdoo problem when trying to change the
+
  //      visibility of a newly created widget (no flushGlobalQueues was called)
+
  //      MSG: Modification of property "visibility" failed with exception:
+
@@ -126,6 +132,7 @@
+
    writeFont( control );
+
    writeToolTip( control );
+
    writeMenu( control );
+
+    writeUserData( control );
+
    writeActivateListener( control );
+
    writeFocusListener( control );
+
  }
+
</pre>
+
  
At the moment, all widget ids are looking like "w1", "w2", "w3". As these ids are generated in the order the widgets are created, it isn't a very good way to handle it. Imagine: You wrote hundred of testcases and then you see: Ah, my application needs an additional label somewhere, all the widgets created after this label have another ID. We are thinking about reinventing the IDs in order to provide more meaningful values which can be used in the tests. But as this is the first attemp, let's go on with what we have.
+
==Preparing the tests==
 +
Now create a new '''java project''' and add the JUnit library. Additionally, you need to add the <code>selenium-java-version.jar</code> (e.g: selenium-java-2.3.0.jar ) and needed libs to your project in order to use the Selenium Remote Control.
 +
 
 +
As RAP applications have a little bit other nature than normal web applications, we need to work around some techniques of selenium. First, you can use commands like <code>click</code> against a target element on your page. The target defined as in <code>id</code> element of your (x)html source. As Qooxdoo doesn't provide ids for their widgets, we need the mentioned [http://wiki.openqa.org/display/SEL/qooxdooExtension Selenium User Extension for Qooxdoo]. With this, all targets prefixed with "qx=" will now use another "find-the-target" algorithm based on <code>UserData</code> provided by Qooxdoo widgets.
  
 
To not prefix all your IDs with the "qx=" special locator, copy this class to your test project to use it as your Selenium connector:
 
To not prefix all your IDs with the "qx=" special locator, copy this class to your test project to use it as your Selenium connector:
Line 118: Line 101:
  
 
public void click(String locator) {
 
public void click(String locator) {
commandProcessor.doCommand("qxClickAt", new String[] { "qx=" + locator});
+
commandProcessor.doCommand("qxClickAt", new String[] { "id=" + locator});
 
}
 
}
 
 
 
public String getText(String locator) {
 
public String getText(String locator) {
return super.getText("qx=" + locator);
+
return super.getText("id=" + locator);
 
}
 
}
 
 
Line 128: Line 111:
 
for (int second = 0;; second++) {
 
for (int second = 0;; second++) {
 
if (second >= 60) System.out.println("timeout");
 
if (second >= 60) System.out.println("timeout");
try { if (isElementPresent("qx=" + locator)) break; } catch (Exception e) {}
+
try { if (isElementPresent("id=" + locator)) break; } catch (Exception e) {}
 
try {
 
try {
 
Thread.sleep(1000);
 
Thread.sleep(1000);
Line 144: Line 127:
 
e.printStackTrace();
 
e.printStackTrace();
 
}
 
}
}
 
 
public String getShellText(String locator) {
 
String text = getText(locator);
 
return text.split("\n")[0];
 
 
 
}
 
}
 
}
 
}
Line 155: Line 132:
  
 
This class is a simple wrapper around the existing <code>Selenium</code> class which helps you with some sort of problems.
 
This class is a simple wrapper around the existing <code>Selenium</code> class which helps you with some sort of problems.
'''Be careful:''' As it's extends the base Selenium class, you'r able to use other methods of the original class which are not overridden by the <code>RAPSelenium</code> class. If you forget to add the "qx=" locator yourself, you'll not get any useful return result.
+
'''Be careful:''' As it's extends the base Selenium class, you're able to use other methods of the original class which are not overridden by the <code>RAPSelenium</code> class. If you forget to add the "id=" locator yourself, you'll not get any useful return result.
  
 
Now we are ready to take off and write the first testcase...
 
Now we are ready to take off and write the first testcase...
 +
(Test case rewrited for jUnit4, feel free to implement it with older version of Junit (without annotations).
  
==Creating the test cases==
+
==First RAP UI Testcase==
To have an idea how a RAP/Selenium test case could look like, see the following:
+
<pre>package testapp;
  
<pre>
+
import org.junit.After;
import junit.framework.TestCase;
+
import org.junit.AfterClass;
 +
import org.junit.Assert;
 +
import org.junit.Before;
 +
import org.junit.BeforeClass;
 +
import org.junit.Test;
  
public class AppTest extends TestCase {
+
public class RapTestCase {
  
 
private RAPSelenium sel;
 
private RAPSelenium sel;
  
private static final String MAIN_SHELL = "w2";
+
private static final String BUTTON = "myButton";
private static final String BUTTON = "w3";
+
private static final String MESSAGEBOX = "w4";
+
private static final String MESSAGEBOX_MESSAGE = "w6";
+
private static final String MESSAGEBOX_OK_BUTTON = "w10";
+
  
protected void setUp() throws Exception {
+
@Before
 +
public void setUp() throws Exception {
 
sel = new RAPSelenium("localhost", 4444,
 
sel = new RAPSelenium("localhost", 4444,
"*firefox",
+
"*firefox C:/Program Files/Mozilla Firefox 4.0 Beta 12/firefox.exe",
"http://localhost:8080/rap");
+
"http://localhost:8080/rap"); //change to working path to you firefox and test application. 
 
sel.start();
 
sel.start();
 
}
 
}
  
 +
@Test
 
public void testButton() {
 
public void testButton() {
sel.open("http://localhost:8080/rap?w4t_startup=testapp");
+
sel.open("http://127.0.0.1:10080/rap?startup=TestApp.entrypoint1"); //change it to feet your configuration (url, name and port).
  
// wait till the element is loaded
 
 
sel.waitForElementPresent(BUTTON);
 
sel.waitForElementPresent(BUTTON);
 
// checking shell title
 
assertEquals("App Title", sel.getShellText(MAIN_SHELL));
 
  
 
// checking button
 
// checking button
assertEquals("Before", sel.getText(BUTTON));
+
Assert.assertEquals("Before", sel.getText(BUTTON));
  
 
// checking message dialog
 
// checking message dialog
sel.click(BUTTON);
+
sel.clickAndWait(BUTTON);
 
+
sel.waitForElementPresent(MESSAGEBOX);
+
assertEquals("MessageBox", sel.getShellText(MESSAGEBOX));
+
assertEquals("Changing the button text now...", sel
+
.getText(MESSAGEBOX_MESSAGE));
+
sel.clickAndWait(MESSAGEBOX_OK_BUTTON);
+
 
 
 +
//  // Close the popup to view go back to the button
 +
sel.clickAndWait("w10"); // was w10 for me, check the Id of yours. You can alternativly set a specific id for the popup validation button.
 
// check button afterwards
 
// check button afterwards
assertEquals("After", sel.getText(BUTTON));
+
Assert.assertEquals("After", sel.getText(BUTTON));
 
}
 
}
  
protected void tearDown() throws Exception {
+
@After
 +
public void AfterClass() throws Exception {
 
sel.stop();
 
sel.stop();
 
}
 
}
 
}
 
 
</pre>
 
</pre>
 
Now let's go through the code to see what's behind all this magic. First I created some constants to avoid dealing with the IDs myself. In the <code>setUp()</code> method, i created a new instance of <code>RAPSelenium</code> which is my interface to the outside world (in this case: the browser). Don't forget to stop the whole thing in the <code>tearDown()</code> method.
 
 
What about the test itself? It's easy...
 
 
We open up the URL where our application is located. Please be sure to modify the url according to your server/port/entrypoint. Also interesting is the browser to be used. In this case, we will use firefox but you can specify whatever browser you want. For Internet explorer, you need to write "*iexplore" or "*custom <path>" for any other browser. See the [http://openqa.org/selenium-rc/tutorial.html Selenium RC tutorial] for more informations about browser launchers. Also take a look at the [http://openqa.org/selenium-rc/experimental.html Using the experimental browser launchers] article.
 
 
But back in town, we don't know when the application is ready to be used, let's wait for the button to be shown in the browser. (see <code>waitForElementPresent</code>). Note that we pass here just a String (the id of the widget) to the method. This will be replaced with "qx=ID" in the RAPSelenium class which then is parsed by the Qooxdoo user extension and Selenium has the right target to do it's operations on it.
 
 
The rest of the testcase is really easy...just some checks if the button has the right text on it, if the shell has the right name...
 
As the Qooxdoo User Extension isn't perfect yet, we need to use <code>getShellText()</code> to test the title of the shell. This may change in the future by a direct call to <code>getText()</code>.
 
 
Now let's click on the button...and what happens?
 
As we know from the source of the sample snippet, there should be a <code>MessageDialog</code> been opened after a click.
 
So wait for it and then test the <code>MessageDialog</code>s title, the message and click it away.
 
 
The last assert only checks if the button has really another text after the <code>SelectionListener</code> got called.
 
 
We are now ready to run our first RAP UI test case. Let's start getting wet...
 
  
 
==Running the Selenium RC server==
 
==Running the Selenium RC server==
Line 237: Line 189:
  
 
Just call this on our favorite shell/commandline:
 
Just call this on our favorite shell/commandline:
<pre><nowiki>
+
<pre>
 
  $ cd <path-to-selenium-rc>/server
 
  $ cd <path-to-selenium-rc>/server
 
  $ java -jar selenium-server.jar -userExtensions <path-to-qooxdoo-user-extension.js>
 
  $ java -jar selenium-server.jar -userExtensions <path-to-qooxdoo-user-extension.js>
Line 245: Line 197:
 
May 29, 2007 5:42:01 PM org.mortbay.util.Container start
 
May 29, 2007 5:42:01 PM org.mortbay.util.Container start
 
INFO: Started org.mortbay.jetty.Server@a62fc3
 
INFO: Started org.mortbay.jetty.Server@a62fc3
<pre><nowiki>
+
</pre>
If you don't get an output like this in the last lines, be sure you have access to the port 4444 or change it with the commandline paramter of the selenium server. See [http://openqa.org/selenium-rc/options.html Command Line Options]
+
If you don't get an output like this in the last lines, be sure you have access to the port 4444 or change it with the commandline paramter of the selenium server.  
 +
See [http://openqa.org/selenium-rc/options.html Command Line Options], you will perhaps also need to rename qooxdoo-user-extension.js to user-extension.js.
 +
 
 +
==Execution==
 +
* start your sample application
 +
* start selenium RC server
 +
* run the test case :)
 +
 
 +
troubleshootings :
 +
* check path to your RAP application and firefox exec.
 +
* check dependancies
 +
* check your rap application entrypoint and activator class.
 +
==And now?==
 +
 
 +
As you see, all that stuff is really hacky and should be used carefully. As this was the first try to combine RAP applications and UI Tests, there is much work to do in this area. When we have some time in the future, we will consider working on an own RAP User Extensions for Selenium with some improvements and also on a - at least - simple infrastructure for your UI tests.
  
==Test it!==
+
* AFAIK the Selenium "type" command is not yet working with qooxdoo textboxes. So be patient...
Now it's really getting interesting...
+
  
The selenium server is running, the applications is running (check that, this isn't covered by this tutorial) and the test cases are ready.
+
If you have great ideas or thoughts how we could improve the whole story, don't hesitate to contact us in the RAP newsgroup or add your thoughts to the Ideas section of this page.
  
So go on and run the test case as you would do with any other JUnit test case.
+
[[Category:RAP]]
If your setup is ok, there should be opened a browser window, some magic will happen and then you hopefully get back to your eclipse with a [http://www.eclipse.org/ajdt/EclipseCon2006/shots/junitTestsPassing.png green bar].
+

Revision as of 03:52, 20 September 2013

| RAP wiki home | RAP project home |

THIS IS EXPERIMENTAL! WE MAKE OUR RESEARCH RESULTS AVAILABLE TO ENABLE FEEDBACK

Writing UI Tests for RAP applications

This document will describe one possible way to do UI tests for RAP applications. With this approach we use the combination of JUnit, Selenium and Selenium RC to have automated UI tests which can be integrated into your JUnit testsuite.

Below is a simple example application to demonstrate the usage of the tool chain.

Requirements

If you don't have it, you need at least these files in order to follow the tutorial:

Extract these files in a directory of your choice.

Creating the sample application

First we need something to test. Therefor I put together a little example application to demonstrate the UI testing approach.

Just create a new plugin project, add org.eclipse.rap.ui.workbench as a dependency, also add all the needed dependency to avoid errors, and create the following class:

package org.eclipse.rap.demo.ui.tests;

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.lifecycle.IEntryPoint;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class TestApp implements IEntryPoint {

  public int createUI() {
    Display d = new Display();
    final Shell s = new Shell(d, SWT.SHELL_TRIM);
    s.setLayout(new GridLayout());
    s.setText("App Title");
    final Button b1 = new Button(s, SWT.PUSH);
    b1.setText("Before");
    b1.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(SelectionEvent e) {
        MessageDialog.openInformation(s, 
                                      "MessageBox",
	                              "Changing the button text now...");
	b1.setText("After");
      }
    } );
    b1.setData( WidgetUtil.CUSTOM_WIDGET_ID, "myButton" );
    s.pack();
    s.open();
    while (!s.isDisposed()) {
	if (!d.readAndDispatch())
		d.sleep();
    }
    return 0;
  }

}

WARNING: this code is not complete, it's a snippet, you will have to realize the Activator class and entry point configuration. As you can see, this is a really tiny RAP example - but big enough to be worth to test it.


At the moment, all widget ids are looking like "w1", "w2", "w3". As these ids are generated in the order the widgets are created, it isn't a very good way to handle it. Imagine: You wrote hundred of testcases and then you see: Ah, my application needs an additional label somewhere, all the widgets created after this label have another ID. That's why we use WidgetUtil.CUSTOM_WIDGET_ID as key for custom widget data. This way we can easily set a human-readable name for each of the widgets under test.

Starting the app

Besides adding the extension for the new entrypoint is it registered there is one important thing to do. We need to activate the UI Test mode in order to get several advantages during running the tests. Just add -Dorg.eclipse.rwt.enableUITests=true as VM argument to your launch configuration.

Note: The VM argument has been renamed in RAP 2.0 to -Dorg.eclipse.rap.rwt.enableUITests.

Preparing the tests

Now create a new java project and add the JUnit library. Additionally, you need to add the selenium-java-version.jar (e.g: selenium-java-2.3.0.jar ) and needed libs to your project in order to use the Selenium Remote Control.

As RAP applications have a little bit other nature than normal web applications, we need to work around some techniques of selenium. First, you can use commands like click against a target element on your page. The target defined as in id element of your (x)html source. As Qooxdoo doesn't provide ids for their widgets, we need the mentioned Selenium User Extension for Qooxdoo. With this, all targets prefixed with "qx=" will now use another "find-the-target" algorithm based on UserData provided by Qooxdoo widgets.

To not prefix all your IDs with the "qx=" special locator, copy this class to your test project to use it as your Selenium connector:

package org.eclipse.rap.demo.ui.tests;

import com.thoughtworks.selenium.CommandProcessor;
import com.thoughtworks.selenium.DefaultSelenium;


public class RAPSelenium extends DefaultSelenium {

	public RAPSelenium(CommandProcessor processor) {
		super(processor);
	}

	public RAPSelenium(String serverHost, int serverPort,
			String browserStartCommand, String browserURL) {
		super(serverHost, serverPort, browserStartCommand, browserURL);
	}

	public void click(String locator) {
		commandProcessor.doCommand("qxClickAt", new String[] { "id=" + locator});
	}
	
	public String getText(String locator) {
		return super.getText("id=" + locator);
	}
	
	public void waitForElementPresent(String locator) {
		for (int second = 0;; second++) {
			if (second >= 60) System.out.println("timeout");
			try { if (isElementPresent("id=" + locator)) break; } catch (Exception e) {}
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	public void clickAndWait(String locator) {
		click(locator);
		try {
			Thread.sleep(1*1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

This class is a simple wrapper around the existing Selenium class which helps you with some sort of problems. Be careful: As it's extends the base Selenium class, you're able to use other methods of the original class which are not overridden by the RAPSelenium class. If you forget to add the "id=" locator yourself, you'll not get any useful return result.

Now we are ready to take off and write the first testcase... (Test case rewrited for jUnit4, feel free to implement it with older version of Junit (without annotations).

First RAP UI Testcase

package testapp;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

public class RapTestCase {

	private RAPSelenium sel;

	private static final String BUTTON = "myButton";

	@Before
	public void setUp() throws Exception {
		sel = new RAPSelenium("localhost", 4444,
				"*firefox C:/Program Files/Mozilla Firefox 4.0 Beta 12/firefox.exe",
				"http://localhost:8080/rap"); //change to working path to you firefox and test application.  
		sel.start();
	}

	@Test
	public void testButton() {
		sel.open("http://127.0.0.1:10080/rap?startup=TestApp.entrypoint1"); //change it to feet your configuration (url, name and port). 

		sel.waitForElementPresent(BUTTON);

		// checking button
		Assert.assertEquals("Before", sel.getText(BUTTON));

		// checking message dialog
		sel.clickAndWait(BUTTON);
		
		//  // Close the popup to view go back to the button
		sel.clickAndWait("w10"); // was w10 for me, check the Id of yours. You can alternativly set a specific id for the popup validation button.
		// check button afterwards
		Assert.assertEquals("After", sel.getText(BUTTON));
	}

	@After
	public void AfterClass() throws Exception {
		sel.stop();
	}

Running the Selenium RC server

The Selenium RC server is a little server written in Java which cares about the interaction between your JUnit tests and the browser instances. As it offers some webservices for us, we need to start it before running our tests.

Just call this on our favorite shell/commandline:

 $ cd <path-to-selenium-rc>/server
 $ java -jar selenium-server.jar -userExtensions <path-to-qooxdoo-user-extension.js>
...
...
INFO: Started SocketListener on 0.0.0.0:4444
May 29, 2007 5:42:01 PM org.mortbay.util.Container start
INFO: Started org.mortbay.jetty.Server@a62fc3

If you don't get an output like this in the last lines, be sure you have access to the port 4444 or change it with the commandline paramter of the selenium server. See Command Line Options, you will perhaps also need to rename qooxdoo-user-extension.js to user-extension.js.

Execution

  • start your sample application
  • start selenium RC server
  • run the test case :)

troubleshootings :

  • check path to your RAP application and firefox exec.
  • check dependancies
  • check your rap application entrypoint and activator class.

And now?

As you see, all that stuff is really hacky and should be used carefully. As this was the first try to combine RAP applications and UI Tests, there is much work to do in this area. When we have some time in the future, we will consider working on an own RAP User Extensions for Selenium with some improvements and also on a - at least - simple infrastructure for your UI tests.

  • AFAIK the Selenium "type" command is not yet working with qooxdoo textboxes. So be patient...

If you have great ideas or thoughts how we could improve the whole story, don't hesitate to contact us in the RAP newsgroup or add your thoughts to the Ideas section of this page.

Back to the top