Community
Participate
Working Groups
Not sure if this capability is available in 2.0 line items, but I thought I should file it anyway. The feature is to ask the SWT team to implement a similar set of APIs that are included in java.awt.Robot, but tailored for SWT widgets. The quick answer to why this is needed is for automating Eclipse UI testing, not through the usual "recording" software products out there, but through writting Java testcases that actually represent your UI automated test. Picture this, when you run your automated JUnit testcases in Eclipse, you are running these automated UI testcases also. So your JUnit testcases are not only for "backend" or "logic" testing! you are also testing your UI functionality. BACKGROUND: ----------- as of JDK 1.3, Sun added a class called java.awt.Robot which is intended for _exactly_ that ! automating UI testing. You can creat events _directly_ at the platform's native input queue. and since you are writting Java code, you can write code that is totally independant of widget location. Your UI layout can totally change and your robot testcase still runs like a charm! bingo, real automation. THE PROBLEM :( Even though I had a prototype working that used Sun's Robot class to automate Eclipse UI testing, there are gltiches. the java.awt.robot class was designed for AWT classes. I worked around some of the problems with using that class with SWT, as opposed to AWT. but still, things where not working as designed just because of the SWT mix with Robot. WHY AM I SAYING ALL THIS :) well, SWT team can easily look into creating a similar class (its a very small set of APIs, but they are very powerful). And if you guys do that, then you have given developers a solution for automating Eclipse UI testing! Im taking the liberty of adding two class just to give you an idea of the sort of thing that I am talking about, and how a UI testcase might look like. ********************************** package org.eclipse.robot; /* * (c) Copyright IBM Corp. 2000, 2001. * All Rights Reserved. */ import org.eclipse.ui.*; import org.eclipse.swt.widgets.*; import org.eclipse.swt.graphics.*; /** * This interface represents the Eclipse-oriented script actions. * <p> * This adds Eclipse functionality to the Robot interface. */ public interface IEclipseRobot extends IRobot { //*******************************// // Eclipse Workbench interface // //*******************************// /** * Opens a Perspective with the given identifier. * <p> * The IObjectIdentifier should be of type Perspective, and the * recognition method is the perspective's name or ID. * If newPage is true, it will open the perspective in a * new page even if the perspective is already open. * If newPage is false, tries to find an open perspective with * the given identifier, and switch to it. If not found, returns * null. * <p> * Returns the opened perspective, or null if command failed. */ public IPerspectiveDescriptor openPerspective(IObjectIdentifier identifier, boolean newPage); /** * Opens a Perspective with the given perspective id. * <p> * The object type and recognition method here are the * the default values for a Perspective. * If newPage is true, it will open the perspective in a * new page even if the perspective is already open. * If newPage is false, tries to find an open perspective with * the given identifier, and switch to it. If not found, returns * null. * <p> * Returns the opened perspective, or null if command failed. */ public IPerspectiveDescriptor openPerspective(String perspectiveId, boolean newPage); /** * Opens a View with the given identifier. * <p> * The IObjectIdentifier should be the * view's name or ID. * <p> * Returns the opened view, or null if command failed. */ public IViewPart openView(IObjectIdentifier identifier); /** * Opens a View with the given id * <p> * The object type and recognition method here are the * the default values for a Perspective. * <p> * Returns the opened view, or null if command failed. */ public IViewPart openView(String viewId); /** * Detaches an open View. * <p> * Clicks on specified view, and drags it outside the current * Eclipse Window. * <p> * Returns IRobotConst.SUCCESS or IRobotConst.FAILURE */ public int detachView(IObjectIdentifier identifier); /** * Detaches an open View with the given Id. * <p> * Clicks on specified view, and drags it outside the current * Eclipse Window. * <p> * Returns IRobotConst.SUCCESS or IRobotConst.FAILURE */ public int detachView(String viewId); /** * Sets the current context to the given object, and gives * it focus. * <p> * Everything is either an * org.eclipse.jface.window.Window or an * org.eclipse.jface.window.Wizard. * The IObjectIdentifier should be the caption string in * the window or the wizard. * ie: only StringIdentifierType is allowed for now. * <p> * Returns IRobotConst.SUCCESS or IRobotConst.FAILURE */ public int setCurrentContext(IObjectIdentifier identifier); /** * Sets the current context to the IWorkbenchWindow with * the given caption, and gives it focus. * <p> * Returns IRobotConst.SUCCESS or IRobotConst.FAILURE */ public int setCurrentContext(String windowCaption); /** * Returns the current context. * <p> * Will return instances of Object types allowed in * setCurrentContext(), or null if command failed. */ public Object getCurrentContext(); //*******************************// // Eclipse UI/JFace interface // //*******************************// /** * Selects a menu item, or a sequence of menu items. * <p> * eg: Perspective->Open->Other... * The menuSequence should be the name of the menu * items in sequence, separated by "->". * <p> * Returns IRobotConst.SUCCESS or IRobotConst.FAILURE */ public int selectMenuItem(String menuSequence); //*******************************// // Eclipse SWT interface // //*******************************// /** * Finds the list of Widgets of the given type in the * current context. * <p> * Returns null if command failed, or non found. */ public Widget[] findWidget(int type); /** * selects the given Widget. * <p> * Returns IRobotConst.SUCCESS or IRobotConst.FAILURE */ public int selectWidget(Widget widget); /** * selects the given Widget. * <p> * Returns IRobotConst.SUCCESS or IRobotConst.FAILURE */ public int selectWidget(IObjectIdentifier identifier); /** * Returns the Control that has focus. */ public Control getFocusControl(); // ps: Display.getCurrent.getFocusControl(); } ******************************** A UI Testcase using the above might look like: ********************************** package org.eclipse.robot.examples; /* * (c) Copyright IBM Corp. 2000, 2001. * All Rights Reserved. */ import org.eclipse.robot.*; /** * From a clean Eclipse UI, this sample performs the following: <br> * ------------------------------------------------------------- <br> * 1. Open Help pespective. <br> * 2. Detach Help View. <br> * 3. Press F1. <br> * 4. Close Eclipse. <br> * <br> * <a HREF="RobotExample1.txt">Source for example</a> * <br> */ public class RobotExample1 { public static void main(String[] args) { try { EclipseRobot robot = new EclipseRobot(); robot.openPerspective ("org.eclipse.help.internal.ui.HelpPerspective", true); robot.setCurrentContext("Help - Eclipse Project SDK"); robot.detachView ("org.eclipse.help.internal.ui.EmbeddedHelpView"); robot.setCurrentContext("Help - Eclipse Project SDK"); // for now AWT constants are used because of dependency on // java.awt.Robot. If Eclipse provides similar class, then // dependency is removed. robot.keyPress(java.awt.event.KeyEvent.VK_F1); robot.keyRelease(java.awt.event.KeyEvent.VK_F1); robot.selectMenuItem("File->Exit"); } catch (Exception e) { e.printStackTrace(); } } } *********************** Another one: *********************** package org.eclipse.robot.examples; /* * (c) Copyright IBM Corp. 2000, 2001. * All Rights Reserved. */ import org.eclipse.robot.*; /** * From a clean Eclipse UI, this sample creates a new File under a * Project called testingProject.<br> * -----------------------------------------------------------------<br> * 1. Open the new Resource wizard. <br> * 2. Select Simple, and File. <br> * 3. click Next. <br> * 4. Select Folder "testingProject". <br> * 5. Type file name, and click Finish. <br> * 6. Close Eclipse. <br> * <br> * <A HREF="RobotExample2.txt">Source for example</A> <br> */ public class RobotExample2 implements IRobotConst { public static void main(String[] args) { try { EclipseRobot robot = new EclipseRobot(); robot.setCurrentContext("Resource - Eclipse Project SDK"); robot.selectMenuItem("File->New->Others..."); // default is window robot.setCurrentContext("New"); // Select item "Simple" from tree ObjectIdentifier objectIdentifier = new ObjectIdentifier (TREE, TEXT_RECOGNITION, "SIMPLE"); robot.selectWidget(objectIdentifier); // Select item "File" from List // this is the long way of doing it! objectIdentifier = new ObjectIdentifier(LIST); objectIdentifier.setRecognitionMethods(new int[] {TEXT_RECOGNITION}); objectIdentifier.setIdentifiers(new String[] {"FILE"}); robot.selectWidget(objectIdentifier); // Select "Next >" button objectIdentifier = new ObjectIdentifier(BUTTON, TEXT_RECOGNITION, "NEXT >"); robot.selectWidget(objectIdentifier); // Select item "testingProject" from tree objectIdentifier = new ObjectIdentifier(TREE, TEXT_RECOGNITION, "testingProject"); robot.selectWidget(objectIdentifier); // Select text area with label objectIdentifier = new ObjectIdentifier(BUTTON, TEXT_RECOGNITION, "File name:"); robot.selectWidget(objectIdentifier); robot.typeString("newFileName"); // Select "Finish" button objectIdentifier = new ObjectIdentifier(BUTTON, TEXT_RECOGNITION, "Finish"); robot.selectWidget(objectIdentifier); robot.selectMenuItem("File->Exit"); } catch (Exception e) { e.printStackTrace(); } } } Im taking the liberty of attaching the
I understand the kinds of capabilities you are looking for. There is no plan to implement this for R2.0, but we do want to look at providing something along these lines at some point. The challenge, of course, is doing this in a way which doesn't require a lot of extra state to be maintained in the widgets or drastic changes in the underlying event model. SWT is so close to the o/s that typically platform specific scripting facilities will work, and hooking into these is likely the direction we would take at the SWT level. Another interesting alternative would be to generalize the mechanisms already found in Eclipse for invoking commands, activating windows, etc. and based on these add "scriptable" u/i support to Eclipse. This would allow Eclipse to be driven by a 'bot without requiring low-level platform specific hacks in SWT. Feel free to continue your investigation of this area, and talk to us about it on the platform-swt-dev mailing list. We're happy to provide insites, but unable to contribute to the effort, at least until R2.0 ships.
Moving from Later.
I have made a complementary request (#64) in the WebSphere Studio Feature Request Database https://www7b.software.ibm.com/webapp/wsdd/studioServlet3 Unfortunately I can't seem to link directly, but the text is: > Developers (esp those using methodologies like XP) and testers need to > be able to automate unit tests for GUIs. AWT frameworks exist for > this, e.g. Abbot > http://abbot.sourceforge.net/ > but they rely on java.awt.Robot and the AWT event model. SWT needs to > provide similar functionality.
The only dependency Robot has on AWT is the waitForIdle function, which posts a Runnable to the AWT event queue and waits for it to get run (which isn't really a wait for idle, BTW, but rather a "wait for the current end of queue"). You probably don't want to depend on the robot's autoWaitForIdle anyway, so you just need a waitForIdle equivalent for SWT. Other than that, I'm not sure what glitches you might be talking about since you don't indicate what specific problems you had with Robot.
Unfortunately I have to answer this from memory!! :( I was looking for my code and the only code I have left is what I have posted here! The problems I had where, like you said with Robor.waitForIdle() and also with Robot.keyPress() keyRelease(). I had to use awt constants (like you see in the sample below) instead of SWT constants to generate the right event in the native OS input queue. and not only that, I could have sworn that not all awt constants would work with SWT, ie: the ket would not be pressed. For example, to simulate pressing F1 I had to use: robot.keyPress(java.awt.event.KeyEvent.VK_F1); which actually worked, butr confusing to say the least to an SWT developer. Others constants would simply not work. hope this helps...
Despite its name, java.awt.Robot appears to be not very AWT- specific. (Note that this is not merely my judgement: it was the conclusion of a long thread on java-gui-testing.) Extending j.a.Robot for SWT appears to involve only + providing an SWT-compatible waitForIdle(). This is somewhat misnamed: it's really wait for the end of the queue," which it hacks by posting a Runnable to the AWT EventQueue and waiting for it to get run. This functionality is required for automation, since one needs to know when one or more events has completed. + extending its automation methods (e.g. keyPress(int), mousePress(int)) to take SWT codes instead of AWT ones. Also please note the advantages that an SWT-compatible extension of j.a.Robot would provide: * it would be useful for UI automation and scripting, e.g. for https://bugs.eclipse.org/bugs/show_bug.cgi?id=37680 > [Plan Item] Add Eclipse automation * it would allow one to leverage much existing GUI test automation tooling. Re "helpwanted": A group within WebSphere Studio is currently attempting to extend an AWT/Swing-based tool to provide whitebox, JUnit-integrated testing for SWT/JFace UIs. We would be delighted to work with you to extend java.awt.Robot for SWT.
*** Bug 38438 has been marked as a duplicate of this bug. ***
Just as FYI for this feature... Thomas L.R., you mentioned that you have SWT specific robot apis. And I had an email with you in regards to abstracting that into a higher level set of APIs that are Eclipse aware, and not just SWT aware. You mentioned it is on your list, and great to know. Another idea just pop-ped to mind. I just spent some time getting my area into JUnit testing, and what I just realized is that I can actually automate most of our *UI* testcases with the JUnit pde plugin that it out there. Its the "JUnit Plugin test" that will be part of the Eclipse 3.0 release. I actually wrote a JUnit testcase that will launche Eclipse, open my perspective, launch our project creation wizard, populate the pages, and then "Finish" the wizard. ! thats exactly what you want in Robot, no? The only difference here is that you are not really generating "true" UI events on the OS event queue. But who cares! :-) most of the code was tested with such a testcase. So I guess what I am saying is that maybe a good place for effort would be to extend the JUnit PDE plugin to include "utility" methods at a hight level that would open a perspective, launch a wizard, launch a view"...etc. ie: high level Eclipse methods that would help when you are doing plugin testcases that have UI in them. just FYI. Mazen Faraj.
mfaraj@ca.ibm.com 2003-09-18 14:34 ------- > I can actually automate most of our *UI* testcases with the JUnit > pde plugin that it out there. Its the "JUnit Plugin test" that will > be part of the Eclipse 3.0 release. Yes, we use pde.junit as well as the Test Collector in WSAD, and also Run>JUnit for standalone SWT UIs. > I actually wrote a JUnit testcase that will launche Eclipse, open my > perspective, launch our project creation wizard, populate the pages, > and then "Finish" the wizard. ! thats exactly what you want in > Robot, no? I also want the ability to test the state of widgets, but that's a separate topic. > The only difference here is that you are not really generating > "true" UI events on the OS event queue. But who cares! :-) Umm ... anyone who wants accurate testing cares :-) The problem with your approach is, fake testing is not testing. Think about what most folks try to do now: they try to have good MVC, such that * most event-related handling takes place in a model * the UI is relatively "thin" They then say, "since all my UI does is call these methods, all I need to do is test these methods." Unfortunately, one finds oneself close to DCUT, or with an urgent APAR, and one diddles the UI to quickly fix the problem. And guess what: the testcases still pass !-) Yet regression still occurs ... because no real testing is getting done. Your approach also doesn't protect you from breakage by others. Suppose you extend another wizard to create your own, and the other group changes their event handling. A fake test won't catch this, because a fake test doesn't test event handling: instead it generates outcomes based on the events you _believe_ will occur. One must generate events in order to thoroughly test a UI. Everything else, no matter how well intentioned, is fake, because it only tests your beliefs regarding how your code works. Fake testing is better than no testing, but it's no substitute for real testing. > So I guess what I am saying is that maybe a good place for effort > would be to extend the JUnit PDE plugin to include "utility" methods > at a hight level that would open a perspective, launch a wizard, > launch a view"...etc. ie: high level Eclipse methods that would help > when you are doing plugin testcases that have UI in them. Here we are in complete agreement. What you are describing are "fixtures": http://junit.sourceforge.net/doc/cookbook/cookbook.htm > Tests need to run against the background of a known set of objects. > This set of objects is called a test fixture. When you are writing > tests you will often find that you spend more time writing the code > to set up the fixture than you do in actually testing values. We absolutely need code that helps one setup a known set of objects: not only workbench artifacts as you describe (e.g. a perspective, a set of view or editor pages), but also resource artifacts (e.g. a web project, a faces-config.xml, database tables). Arthur Ryman posted ws-dev recently about the need for groups to develop and maintain such fixture code for use in testing; I concur heartily.
steve_northover@ca.ibm.com 2003-09-17 11:15 ------- > We have done no work on this item because it was deferred from the > Eclipse 3.0 plan. Eclipse had no requirement for this and Eclipse > drives SWT. > Does it work on every platform? We have not tested this, but it should run on any platform that supports Sun's JDK. > Does it use AWT robot? It uses java.awt.Robot, but this could be worked around. What I mean: The fundamental problem of automation is, how to get events into the native queue. abbotforswt tries to be a thin layer over some of the lower levels of Abbot, which uses awt.Robot. awt.Robot uses a RobotPeer > /** > * RobotPeer defines an interface whereby toolkits support automated > * testing by allowing native input events to be generated from Java <snip> > */ > public interface RobotPeer > { > public void mouseMove(int x, int y); > public void mousePress(int buttons); > public void mouseRelease(int buttons); > public void keyPress(int keycode); > public void keyRelease(int keycode); > public int getRGBPixel(int x, int y); > public int [] getRGBPixels(Rectangle bounds); > } (a pretty-basic automation interface, though I'd factor out the screen-capture stuff), and uses its SunToolkit as a factory for the implementation. How to do this with other JDKs (e.g. Apple, Blackdown, Hursley, J9)? If they also provide "toolkits [that] support automated testing," and therefore an interface like the above and a factory for its implementation, a foo.Robot for each other toolkit would be straightforward (and might already exist). If they do not, that would seem to be a defect, and its rectification would seem a legitimate request.
-------- Original Message -------- Subject: Re: [IBM JDK] automation support? Date: Fri, 19 Sep 2003 09:39:57 +0100 From: Neil Masson <nmasson@hursley.ibm.com> Reply-To: nmasson@nospam.hursley.ibm.com Organization: IBM Newsgroups: forums.software.java References: <bke3fb$qcf$1@w3pilot2b.pok.ibm.com> Tom, java.awt.Robot and java.awt.AwtPermission are part of the J2SE spec and so all compliant JDKs will have these classes and those on which they rely. IBM's JDKs are no exception. Indeed they have the same implementation using java.awt.peer.RobotPeer.
Thomas, you are absolutely right. Being able to generate events directly on the native queue hence replicating a true user action is important to have a "real" testcase. BUT, you can do both, a bottom up approach AND a top down approach. You can be finishing up the ABBOT apis, at the SWT level. Some other team can be coding the re-usable JUnit Eclipse fixtures, without the event model apis. Both teams meet half way. The fixtures can be then modified to instead of having something like wizard.performFinish() (which is what I do today), they would have abbotEclipse.closeWizard(myWizard), which will generate a mouse click on the Finish button of the passed wizard. Im not aware of Arthur's request (Im not in that group), but it sounds like an even higher level layer on top of the Eclipse fixture layer. A layer that understands a Web Project, as opposed to a project. Just a thought... :) Mazen Faraj.
-------- Original Message -------- Subject: Re: [IBM JDK] security model? Date: Fri, 19 Sep 2003 10:41:17 -0400 From: Richard L. Kulp <richkulp@NO--SPAM.us.ibm.com> Organization: IBM Newsgroups: forums.software.java I can't swear to it, but IBM typically doesn't reinvent such things. Under the covers they probably use the sun security model. In fact I just looked at the IBM jre that we ship with WSAD and it doesn't have its own security manager, it uses Sun's. -------- Original Message -------- Subject: Re: [IBM JDK] security model? Date: Fri, 19 Sep 2003 10:52:11 -0400 From: Richard L. Kulp <richkulp@NO--SPAM.us.ibm.com> Organization: IBM Newsgroups: forums.software.java In addition, AWTPermission isn't a Sun class, it is a java.awt class, so all of the SecurityManagers should know about it. Though they may decide to deny permission by default. That is their choice.
Mazen: it appears we again have "a meeting of the minds" :-) Mazen Faraj 2003-09-19 11:58 ------- > You can be finishing up the ABBOT apis, at the SWT level. Actually, AFAICS the only work that remains "at the SWT level" is to have a consistent location-finding API for all Widget's, rather than only those extending Control. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=38436 Fortunately the non-Control Widget's are _relatively_ few and minor. What we're working on now are workbench extensions, such as you mention: for wizards, editors, views, perspectives, etc. > Some other team can be coding the re-usable JUnit Eclipse fixtures, > without the event model apis. Both teams meet half way. Correct. In fact, the fixtures need not have any JUnit-specific content: they need only be callable from setUp(). I will cc: you regarding current efforts in this direction. > The fixtures can be then modified to instead of having something > like wizard.performFinish() (which is what I do today), they would > have abbotEclipse.closeWizard(myWizard), which will generate a mouse > click on the Finish button of the passed wizard. Actually, we do better than that: we actually click on the Finish button! I have a working test case that does exactly that :-) But 2 quibbles: * Again, IMHO "real" testing doesn't _tell_ the Wizard what to do; it just mimics what the user does. (Only faster and more repeatably :-) * What you're describing would take place in a testcase, not a fixture.
Nick Edgar 09/17/2003 11:07 PM > it looks like the current implementation of java.awt.Robot would > bring in more stuff than we would like. It refers to AWT-specific > classes (GraphicsDevice, AWTPermission) and VM-vendor-specific > classes (RobotPeer, SunToolkit). These classes may not exist on > non-Sun VMs (e.g. IBM Hursley or J9). Fortunately, no. IBM JDK is J2SE-compliant, and uses the same implementation as the Sun VM. I have also been told that "J9 [as] the default runtime for WSAD 5.1 ... uses the IBM J2SE class library." (The WSDD J9 is apparently different). One holdout is Jikes: it is not yet J2SE compliant. They are seeking compliance, but use the GNU Classpath libraries, which are not yet AWT-complete.
Kevin Dale has removed all Abbot dependencies from abbotforswt's "base Robot" (i.e. our SWTized equivalent of java.awt.Robot). Thus it should be suitable for donation to Eclipse, if desired. The code is in our CVS; feel free to inspect. Unfortunately * non-IBMers: the code is presently not directly available to you. However · we are seeking approval to open-source abbotforswt · we may be able to provide pre-OSS-approval licensing to you: please post me if you are interested. * IBMers: lawyers got upset the last time I mentioned how to get to the internal CVS on a public forum, even though · the repository is inside the firewall · the repository provider is a project that has been discussed publicly So if you don't know how to get to our CVS but you would like to, please post me. TIA, Tom Roche <tlroche@us.ibm.com> abbotforswt admin
Please note that * Abbot http://sourceforge.net/projects/abbot is available under CPL. * abbotforswt has received all preliminary approvals to OSS (to Abbot), and goes for final approval 27 Jan 04. * a binary plugin for Abbot (AWT/Swing) 0.11.0 is available @ http://prdownloads.sourceforge.net/abbot/abbot-0.11.0-eclipse.zip?download https://w3.opensource.ibm.com/frs/viewRelease.php?release_id=545&group_id=1023 * a binary plugin for abbotforswt (containing our SWT-ized Robot) is @ https://w3.opensource.ibm.com/frs/viewRelease.php?release_id=545&group_id=1023 It prereqs the Abbot plugin. * EA users report success with abbotforswt on both Windows and Linux. (Abbot is widely used on many platforms.)
steve_northover@ca.ibm.com 2004-02-19 12:43 >> Is [21083] the same as 15025? David_Whiteman@us.ibm.com 2004-02-19 12:50 > Sort of... Not. abbotforswt https://w3.opensource.ibm.com/projects/abbotforswt/ already has a working SWTized Robot; its remaining defect involves difficulty finding non-Control Widget's https://bugs.eclipse.org/bugs/show_bug.cgi?id=38436 e.g. for driving cascading menus. (IIRC non-Control Widget's can usually be found by walking the hierarchy, but that always harms performance, esp when driving busy environments like a runtime workbench.) > In other words, doing the work for bug 15025 would involve adding > support for posting key and mouse events to the OS (as bug 21083 > describes) abbotforswt's Robot already does post key and mouse events, using a java.awt.Robot. We have working, JUnit-driven demos and test cases. HTH, Tom Roche, Rational Developer Model2 Tooling, abbotforswt admin
Available in v>20040323: Display.post(Event e) Special thanks to Sebastian Peleato from University of Waterloo for contributing this new API. Please see the following snippet to see how to generate system events under SWT. http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/platform-swt- home/snippits/snippet142.html
marking as fixed v>20040323
*** Bug 21083 has been marked as a duplicate of this bug. ***