When should I use an Abbot script versus a plain old JUnit TestCase?
Usually if you are writing unit tests or tests for small groups of components,
you should use a
ComponentTestFixture
which is derived from
junit.framework.TestCase, explicitly invoking actions and
assertions on your small number of gui components. See
this tutorial for an example of this
approach.
Otherwise use scripts, since it lowers the complexity of the overall test and
makes it much easier to edit. The script provides easy mnemonics for
referenced components. It also abstracts the test into simple actions and
assertions. These elements become much less obvious within a long test
written entirely in Java code.
How do I test an applet?
Instead of a Launch step, use the Appletviewer
step. It will run your applet under appletviewer. You can specify the
applet tag attributes as well as parameters for the applet.
I don't see the functions I need.
The Call step is very
flexible; you can specify an arbitrary class and invoke a method on it, or you
can invoke any method on an existing ComponentTester or Component.
Abbot is also very extensible. You can add custom
Step classes that do exactly what
you want, custom parsers
for translating Strings into custom objects, or add
ComponentTester classes for
your own components. You can also add methods (actions or assertions) to any
of the existing testers and contribute them back to the project.
Implementation details are provided in the javadoc description of each of
those classes. Most things only require that you make the new class
available in the classpath; the framework will pick up the new features
automatically, providing you adhere to some simple conventions.
The script language may incorporate a more
extensive basis in the future (such as Jython or beanshell), but that hasn't
yet proved to be a high priority.
Classpath, classpath, wherefor art though classpath?
There are two methods of specifying the classpath for your application
under test.
Specify the classpath in the script Launch step.
A custom class loader (abbot.script.DynamicClassLoader) will be used to load
your classes from the classpath you specify. Relative paths are evaluated
based on the current directory (user.dir). If your code under test uses
ClassLoader.getSystemClassLoader to obtain the "current" class loader, you
should fix the code to use Class.getClassLoader or
Thread.getContextClassLoader instead.
Pass the classpath to the VM on startup.
This method is not preferred. Don't do it. Only the framework classpath
(i.e. abbot.jar and/or costello.jar) belongs here.
There are some cases where you might want to use this method (such as when you
need to dynamically generate the classpath for a number of different runs).
If so, then the classpath in the launch step should be left blank, and the
launch step should be set to fork="true", unless you don't care about
reloading all classes on each test run.
Pass the full classpath to the Launch step, and part of the classpath
to the VM on startup.
Sometimes an application will report that it cannot load resources that it can
find when not running under the Abbot framework. One common cause is that
ClassLoader.getSystemClassLoader() is often used when
getClass().getClassLoader() should really be used instead. The class loader
returned by the former is the class loader for the Abbot framework (which uses
the classpath passed to the VM on startup). In the latter case, the class
loader is that created by the Launch step for your app. You can work around
the problem by either a) changing the code to be correct or b)
putting the path to your resources in the classpath of the startup VM.
How do I set java.library.path? How do I set other VM settings?
Except for the classpath, all VM settings must be set when the VM is
launched. That means you need to set them either when launching Costello or
when launching your JUnit test runner.
How do add assertions for something on a modal Dialog?
How can I easily integrate a group of scripts into JUnit? I don't want to
have to write a TestCase every time I add a new script.
The class
junit.extensions.abbot.ScriptTestSuite has a main method which
accepts a list of Abbot script filenames. It will run the standard JUnit text
UI TestRunner on each of those scripts.
You can also derive from the
ScriptTestSuite
or
ScriptFixture
classes as described in the documentation for those classes to get other types
of groupings for scripts, including collecting all scripts from a given
directory and recursing into subdirectories, or collecting all scripts
matching a particular filename pattern.
My application appears to start, but then nothing happens.
If your main routine doesn't return, or if it performs GUI operations (such as
displaying a Dialog) prior to returning, you need to set your Launch step to
"threaded". This causes the script to not wait for your main routine to
finish and allows it to continue generating events for your code under test.
When running my script I get an InvalidScriptException complaining about a property not recognized for SAX.
Normally it's the
"http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation"
property that's not recognized. The reason for this that the Abbot tries to do
schema validation on the script on load but the parser used does not support
schema validation. This may happen in the case that the classpath contains an
entry to an older version of the xerces XML parser. This feature is tested
with Xerces 1.4.4 and Xerces 2.4.0 (this is the version delivered with
Abbot). Newer version should work also. The solution would be to change the
classpath so that the recomended versions of Xerces will be used. If this is
for whatever reason not possible in your case it's possible to switch off the
vaildation feature by providing the system property
-Dabbot.script.validation=false to the VM.
Running tests headless
Sometimes you'd like to be able to run tests without them taking over your
computer. Windows systems can run in "service" mode; if you have sshd (which
allows remote login to your w32 system) running or can otherwise launch a
terminal login session, this session will run with its own desktop which is
invisible to the main display. The tests will run in AWT mode, so certain
tests (notably drag/drop, which requires native OS events) will not work.
X11-based systems can run under any display, not just that of the logged-in
user.
Matching regular expressions
Most expressions within a script can be replaced with a regular expression.
For instance, if the title of a window is "Window (FFF)", where "FFF"
represents a file and may change, you can change the title attribute of its
component reference to "/Window .*/" so that it always matches the variable
title.
Matching multiple lines
The regular expression package supports matching of carriage return and
newline characters. Within a regular expression, the string "(\r?\n)" will
match cross-platform.
Keyboard Mapping
Different keyboard layouts require different keystrokes to generate any given
key. Abbot attempts to figure out the correct keystroke, but may need
some help on non-US keyboard layouts and/or locales. The keystroke may also
vary by platform. Currently available keymaps are found in
the abbot.tester.keymaps package.
If your keyboard layout/locale is not yet supported, you can run
abbot.tester.MapGenerator to generate appropriate key maps, then
submit those to the Patches area on the project site.
If a key mapping can't be found, only the resulting String is generated.
Missing Images and/or Resources
If your application uses Class.getSystemResource(String)
instead of Class.getResource(String), it's probably not
finding the resources in question in the active class path. When applications
are launched from Costello, Costello's classpath is the one used by
getSystemResource. To access your application's launch
classpath, you should use Class.getResource(String) from one of
your application's classes.
How can I contribute to the project?
There are many things that would help move this project along. In addition to
simply using it to test your GUI and providing feedback and bugreports to the sourceforge page, you can do any of
the following:
Write a ComponentTester class for a component that doesn't yet have one,
or add more accessors and/or actions to existing ones that need more.
Write a Recorder class for a component that doesn't yet have one. The
recorder should capture those actions exported by the corresponding
ComponentTester class.
Write a user's manual for the editor.
Contribute your general GUI testing experience to the
yahoo discussion group. Note that this group is for discussion of general
GUI testing issues and practices; questions specific to Abbot should be
directed to the Abbot user's
mailing list on SourceForge.