1.1 What is JDemo?
1.2 What is JDemo not?
1.3 What can JDemo be used for?
1.4 JUnit as Role Model
1.5 Differences between JUnit and JDemo
1.6 When to write a Demo
1.7 Installing JDemo
1.8 How to write a Demo
1.9 How to run a Demo
1.10 GUI Demos
1.11 More about JDemo
2.1 Example application
2.2 Demos for the application
2.3 Demos for multiple purposes
3.1 Basic Framework Interfaces
3.2 Demo Execution and Life Cycle
3.2.1 Standard Demo Execution
3.2.2 Demo Execution States
3.2.3 GUI Demo Execution
4.1 Choosing an Appropriate Base Class
4.2 Class Hierarchie
4.3 AbstractDemoCase
4.3.1 API Description
4.4 PlainDemoCase
4.4.1 Example Usage
4.5 DemoCase
4.5.1 API Description
4.5.2 Example Usage
4.6 GuiDemoCase
4.6.1 API Description
4.7 AwtDemoCase
4.7.1 API Description
4.7.2 Example Usage
4.8 SwingDemoCase
4.8.1 API Description
4.8.2 Example Usage
4.9 LookAndFeel with SwingDemoCases
4.9.1 API Description
4.9.2 Example Usage
4.9.3 Comments
4.10 SwtDemoCase
4.10.1 API Description
4.10.2 Example Usage
5.1 Launching
5.2 Usage
6.1 JDemo Wizards
6.2 JDemo Launch Type
6.3 Misc
6.3.1 Recreate Demo Suite
6.3.2 Go to Referring Demos
7.1 Demo Identifier
7.2 Capturing Textual Output
7.3 Capturing File Output
7.4 Making Screenshots
7.5 Ant Tasks
7.5.1 Capturing Text Output
7.5.2 Capturing File Output
7.5.3 Making Screenshots
7.5.4 Known limitations
7.6 Image processings
7.6.1 Generic image processings
7.6.2 Composing images
8.1 Automated conversion from demos to tests
8.2 Peculiarities with demo-tests
8.3 Evaluation
9.1 JDemo Annotation
9.2 Example
10.1 JDemo CVS
10.2 Writing your own DemoRunner
10.3 Integrating the DemoRunner into other Applications
11.1 Batch Capture
11.2 Executing Sequences of Demos
Markus Gebhard
markus@jdemo.de
http://www.jdemo.de
| Date | Author | Version | Changes |
|---|---|---|---|
|
8th January 2005 | Markus Gebhard | 1.2 | 1. Adjusted all chapters to the new JDemo 1.2 version. 2. Added an index to the PDF version. 3. Adjusted version number to release. |
|
2nd September 2004 | Markus Gebhard | 0.5 | Minor corrections, added a new item to the future development chapter. |
|
16th August 2004 | Markus Gebhard | 0.4 | Adjusted examples to the new JDemo 1.1.1 version. |
| 23rd July 2004 | Markus Gebhard | 0.3 | Adjusted all chapters to the new JDemo 1.1.0 version. |
|
8th May 2004 | Markus Gebhard | 0.2 | 1. Added a chapter about a typical usage scenario 2. Added a chapter about demos as unit tests 3. Modified all other sections to fit the current JDemo release |
| 18th October 2003 | Markus Gebhard | 0.1 | First public version |
1.1 What is JDemo?
JDemo is a new demonstration framework written in and for the Java (Java is a trademark or registered trademark of Sun Microsystems, Inc. in the U.S. or other countries.) programming language. Its concept and implementation is based on the open source regression testing framework JUnit (http://www.junit.org) by Erich Gamma and Kent Beck. Although being quite different from JUnit, there are a lot of similarities.JDemo provides a uniform and straightforward way for writing code snippets similar to unit testing code. The code snippets can be used to demonstrate both the code usage and the output of the program - either to the screen, to a file or just as plain text. Furthermore the demo code can be used for documentation purposes.1.2 What is JDemo not?
JDemo is not an extension to JUnit. As will be described in the following sections, there are fundamental differences in the concepts of both frameworks. Also JDemo is not a substitute for unit tests. In fact using JDemo in practice for a while has shown that using both, JDemo and JUnit side by side, makes a perfect combination.Finally JDemo is not an academical project. On the contrary, most of the framework has been developed while working on serious (well, and also some not so serious...) projects. It has evolved and has already proven to be very useful for many purposes. Now that it is almost grown up, I want to share it with the open source community.1.3 What can JDemo be used for?
Being both very simple and flexible, JDemo has multiple benefits. Here is a list of the most important ones I have found:The list could be extended, but I think it is now time to explain the framework and show how to write a simple demo. Before that, I want to explain what the idea of JDemo goes back to though.
- Interactive testing
Writing demos for GUI components enables developers to run the dialogs they are working on, without having to start the whole application. They can pick a single component or a whole frame at a time - whatever is appropriate. This saves a lot of time and simplifies test driving the user interface or any other part of the application.- API improvement
Just like with unit tests, the demo code is written from the point of view of a developer who uses a given API, or - when writing the demo before the code - who is about to design the API. This will most likely lead to a better API.- Decoupled code
Writing code snippets, only demonstrating a small piece of the code, requires a more modular code design. This most likely leads to better decoupled software components.- Code documentation
When done with some care, the demo code demonstrates usage of the production code by providing simple code snippets. Those are a valuable resource for documenting proper usage.- Easier Library evaluation
When you are looking for a specific component for your GUI (graphical user interface), for example, it is much easier to start the demos for a given library to evaluate it, than to write your own code to fire up the library. Most commercial libraries come along with sample applications or other kind of proprietary demonstration code. Using a uniform way for writing and running demonstration code like with JDemo makes it much easier for developers to find out whether the library fits their needs and how it must be used.- Reduced code duplication
The JDemo framework classes provide a lot of convenience methods, so the developer does not have to care aboutmainmethods, creating application frames or whatever. Obviously this leads to fewer code duplication.- Automated creation of documentation
Each demo has a unique identifier that can be used to automatically run the demo, e.g. from within an Ant (http://ant.apache.org) build script. The output can automatically be captured either as text, as file or as a screenshot in case of GUI demos. This enables software developers to provide an automatic and reproducible way of creating up-to-date screenshots or sample output for the user manual. (Now doesn't that sound pleasing in a time where most manuals are already out of date when finished?)1.4 JUnit as Role Model
One day in early 2003 I found myself writing a JUnit test method that was not really meant to be an automated test, but rather a little piece of code making some kind of graphical output, I was interested in. I was tempted to use the unit test approach because I already had some code for initializing my software library in a unit test. By adding a few lines likeThread.sleep(10000)andframe.show()to the test and starting the TestRunner I was able to test drive the program and evaluate its output.For those being familiar with JUnit, it is obvious that using unit tests for interactive testing just does not make sense. Unit tests are meant to be run and evaluated automatically. Each test is only run once and all tests in the selected test suite are being run. This other kind of test code - from now on called demo code - requires a slightly different approach. All demos in a suite must be presented to the user, who then can arbitrarily pick a demo to be executed. It depends on his intention, what the demo is used for: If he is a developer working on the code, he probably wants to run the demo in order to actually see that the demonstrated program part behaves in the right way. As a developer who is looking for a code library, he probably wants to see if the library fits his needs or how its API can be used. With these totally different aims it is clear that demos are different from tests and mixing up demo and test code must be avoided.However there are a lot of advantages regarding the simplicity and the concept of writing unit tests, so I decided to make JDemo similar to the approved JUnit framework.1.5 Differences between JUnit and JDemo
Developers familiar with unit testing will only have to learn a few things in order to use JDemo.
Here is a list of the main aspects and differences one has to be aware of:
- Demo method names start with
demo...()rather than withtest...().- In demos there are no
assert...()statements. Each demo method must contain a call to ashow...()method instead.- Demos are not run automatically but rather presented to the user in a hierarchical view. The user can pick and start the demos arbitrarily.
- Demos are not meant for ensuring the implementation to work as specified, but rather to demonstrate the code usage and the output to the user.
- Test cases and test suites in JUnit are analogous to demo cases and demo suites in JDemo.
- Demo cases can implement
setUp()andtearDown()methods, that (just as in JUnit) will be executed before/after the demo method.- Executing all demos in a demo suite at once does not make sense (in most situations), so demo suites in difference to test suites can not be run.
1.6 When to write a Demo
There are some situations indicating that it is a good idea to write a demo:
- Whenever you are tempted to write a
mainmethod, although you are not writing an application.- When you are developing a program or library and want to see some output without starting the whole application.
- Whenever you want others to see how to use your API. Writing demo code that actually works and is being maintained leads to very useful documentation, always being up to date. I know that this is also being claimed for unit test code, but I found that demo code is much more useful here.
- Whenever you want to be able to automatically generate program output, e.g. for documentation purposes.
1.7 Installing JDemo
Before writing the first demo, you will have to install the framework. Fortunately JDemo installation is simple:That's it.
- Download the distibution package from the JDemo homepage.
- Unzip it to a new directory.
- Add
jdemo.jarto yourCLASSPATH.
Advanced users can reduce dependencies: Thejdemo.jarconsists of the smaller librariesjdemo_core.jarandjdemo_runner.jar. Both of them are contained in the download package, too. At compile time you only will need the core library. When executing demos you will also need the runner library. The Eclipse plugin (see chapter 6) for example contains a runner itself, so Eclipse users will only need the core library.1.8 How to write a Demo
Similar to unit tests, demos are public methods nameddemo...(). They must be implemented in subclasses of one of the demo case implementations provided by the framework (e.g.de.jdemo.framework.DemoCase). Demo methods must not have any parameters and their return type must bevoid. They may declare to throw any kind of Exception, although a valid demo should never throw any (unless it demonstrates how to throw an Exception...).The probably most simple demo is a hello world demo:
This trivial demo class contains a single demo that will print out "
public class HelloWorldDemo extends de.jdemo.framework.DemoCase {
public void demoHelloWorld() {
show("Hello World");
}
}
Hello World" when being run. Note that the name of the demo is derived from the method name, so our first demo's name is "Hello World".1.9 How to run a Demo
There are various ways for starting a demo. One is to call a JDemo runner from the command line. The command
will start the demo above by using the Swing based runner contained in the JDemo library. Note that JDemo has to be installed as described in section 1.7. Figure 1.1 shows the DemoRunner after executing the Hello World demo.java de.jdemo.swingui.DemoRunner HelloWorldDemo
An alternative way for running a demo is to provide the code for starting the DemoRunner in themainmethod of the demo class itself:
Note that this is not the recommended way for starting the DemoRunner: Directly referencing the DemoRunner from within a demo class adds lots of dependencies. The decision about what runner application to use should be made by the user at run time, not by the developer at compile time.
public static void main(String[] args) {
de.jdemo.swingui.DemoRunner.run(HelloWorldDemo.class);
}
Rrunning one or more demos from within an integrated development environment might be much more convenient - at least when there are plugins or extensions for JDemo being available and installed. For the popular Eclipse IDE, for example, there is a plugin available (see chapter 6).1.10 GUI Demos
Besides the text basedDemoCaseclass, JDemo also contains demo case base classes providing convenience methods for GUI demos using AWT, Swing and SWT (for a complete overview of the available demo case base classes refer to section 4.1.For example, imagine you have written the code for a Swing GUI componentMyDice, showing the top side of a die.Here is what a valid demo for this class could look like:
The demo class subclasses
public class MyDiceDemo extends de.jdemo.extensions.SwingDemoCase {
public void demo6Dice() {
JComponent diceComponent = new MyDice(6);
show(diceComponent);
}
}
de.jdemo.framework.extension.SwingDemoCasebecause it uses a Swing component for output. Note that there is no need to care about adding the component to aJFrameorJDialog. TheSwingDemoCaseclass does all the work for you in the providedshow(...)method.Figure 1.2 shows what you will see when running the demo.
Now lets imagine your dice component also has a default constructor (without a parameter) for creating a die with a random number. It is a good idea to also provide a demo for that by adding a second demo method to theMyDiceDemoclass:
Running the DemoRunner will now present two demo cases to the user. Figure 1.3shows example screenshots.
public void demoRandomDice() {
show(new MyDice());
}
The complete source code for this and other simple examples of JDemo usage can be found in the examples folder of the JDemo download package.1.11 More about JDemo
This overview was meant for giving you an idea of what JDemo is all about. However there is a lot more to learn about it. So read on to the next chapters for a more detailed description of the framework and its API.
2.1 Example application
Let us have a look at a typical software application as shown in Figure 2.1. In order for the main application to start, you have to successfully log in at a login dialog. The main application frame consists of a tree, a list and a few other components. From there you can start a wizard for importing some files. Once there are files imported into the application you can move on to an export dialog that in the end creates a html file.![]()
Figure 2.1: Draft of a typical software application
Obviously the application can be divided into separate parts (and I am pretty sure this structure will also be reflected by the modules or packages in the implementation):During development most of the time software developers will work on one of these parts without caring much about the others. This is also true for unit tests, which are meant for testing small units of code. But what about the dialogs? If I want to see the html export dialog I have to start the application, log in, import files, etc. I have to navigate the whole way through the application until I finally see it on the screen. Of course the same procedure has to be performed if I just want to have a look at some example html output.So all that I want is some simple way to demonstrate certain parts of the application. But when looking into software engineering books I cannot find a single sentence about this kind of code demonstration.
- the login dialog
- the main application frame
- the import wizard
- the html export
2.2 Demos for the application
JDemo provides a consistent way for writing and organizing code for demonstrating parts of a software application. So for the application described in the previous section we would write a demo for the html export dialog, for example. Using theSwingDemoCaseclass described in section 4.8, the demo might look somewhat like this:At first some example data is being created. Then the export dialog is being created using this data and it is being shown by calling a convenience method in
public void demo() {
ExportableData data = createExampleExportData();
ExportDialog dialog = new ExportDialog(data);
show(dialog);
}
SwingDemoCase. The demo method contains everything being neccessary for demonstrating the export dialog - and nothing else.As we also want to see what the html output looks like, we continue writing a demo for showing some example output:The code uses some convenience methods from the
public void demo() throws IOException {
File outputFile = createTempFile(".html");
ExportableData data = createExampleExportData();
new HtmlFileExport().export(data, outputFile);
show(outputFile);
}
DemoCaseclass described in section 4.5 for creating and showing a temporary file.Now these two code snippets and others are then being arranged into suites of demos. The suites from each software module on their part can be arranged in another suite and we will end up with a tree of demos as shown in figure 2.2.
From now on for each part of the application there is a demo available. In the next section we will see what they can be used for.2.3 Demos for multiple purposes
Figure 2.3 shows what demos are useful for in the various phases of software development.![]()
Figure 2.3: Field of applications for demos in various phases of software development
The most interesting fact is that demos are not only useful during implementation, but also for deployment and maintenance.
This chapter has not been finished and will be extended in a future version of this document.
3.1 Basic Framework Interfaces
Figure 3.1 shows the base interfaces of the JDemo framework. As you can see, demos use the composite design pattern.IDemoCaseobjects are actual demo implementations. Each demo has a unique identifierDemoIdentifierconsisting of the fully qualified demo class name and the demo method name. Demos can be aggregated inIDemoSuiteobjects.![]()
Figure 3.1: Base interfaces of the JDemo framework
Compared to the JUnit framework there are two main differences:Figure 3.2 shows the interface of the
- The common superinterface
IDemodoes not provide any means for starting the demo. This is because it does not make sense to start a complete suite of demos at once. OnlyIDemoCaseimplementations are supposed to be executed. The common superinterface ofIDemoCaseandIDemoSuiteis only there in order to be able to compose the demos into a tree structure.- There is no method to run a
IDemoCaseobject directly. The reason is that running demos has proven to be more complex than running tests. So instead of a simplerunmethod for executing the demo, there is aIDemoCaseRunnableobject being created, that takes care of the execution process.IDemoCaseRunnable. The runnable carries information about the current state of the demo it has been created on. The framework contains a typesafe enumeration implementationde.jdemo.framework.state.DemoStatefor the execution states. Section 3.2.2 describes the various states of a demo. A demo runner application can attachde.jdemo.framework.state.IDemoStateChangeListenerobjects to the DemoCaseRunnable in order to react on state changes (see figure 3.2). When the demo has crashed, thejava.lang.Throwableobject that describes the problem can be requested using thegetThrowable()method.![]()
Figure 3.2: The runnable for executing a demo case.
Being aRunnable, it can be started in a separate thread and execute the demo. Theexit()method is being called from within the DemoCase or the runner for normal demo termination. If the user requests to cancel the demo from outside (for example by pressing a stop button in the demo runner application), thecancel()method is used instead to interrupt execution.3.2 Demo Execution and Life Cycle
This section describes the execution of demos in JDemo using the DemoCaseRunnable introduced in the previous section.3.2.1 Standard Demo Execution
Figure 3.3 shows the simplified sequence diagram of the execution of a demo (Note: Please don't mix up theDemoRunnerand theDemoCaseRunnable: TheDemoCaseRunnableis the default implementation of theIDemoCaseRunnableinterface described in the previous section, whereasDemoRunneris a different class, that initiates the execution of a demo.) .![]()
Figure 3.3: Sequence diagram of demo execution.
Demo execution is separated into two steps:
- 1. A DemoCaseRunnable is being created
In order not to interfere with other demo executions, the DemoCase is cloned before creating a runnable. The runnable is then being created on the clone and attaches itself to the clone as its runnable. This tight coupling of DemoCase and DemoCaseRunnable is necessary because for GUI demos it must be possible to exit the demo execution from inside the demo code.- 2. The created DemoCaseRunnable is being run
The DemoRunner invokes the methodrunon the DemoCaseRunnable. In the current framework implementation the DemoRunner actually creates a new thread on the DemoCaseRunnable and starts it. However for simplification this is not shown in figure 3.3.The DemoCaseRunnable then takes control of the demo execution process. After calling thesetUp()method in the DemoCase, the actualdemo...()method is being executed. Finally the demo is terminated by callingtearDown().Note that for "symmetry" with JUnit test cases thesetUp()andtearDown()methods inDemoCaseare protected and can not be called from the DemoCaseRunnable directly. So the public delegate methodsexecuteSetUp()andexecuteTearDown()are invoked instead.3.2.2 Demo Execution States
During execution, each demo goes through a number of states. For implementing or running demos you will not have to care much about the different states. However, for a better understanding of the framework we will have a look at them.
Initial
After being created the DemoCaseRunnable's state is INITIAL. At this moment the runnable holds a new clone of the DemoCase object and none of the DemoCase's code has been executed (besides static initializers and the constructor).Starting
The state is set to STARTING before thesetUp()method of the DemoCase is being called.Running
Right before calling the actual demo method, the state is changed to RUNNING. It stays running until the demo finishes or crashes.Finished
A demo is FINISHED as soon as thetearDown()method has been executed. Usually thetearDown()method is called by the DemoCaseRunnable right after when thedemo...()method returns. However this is not true for GUI demos (Refer to the next section for a detailed explanation regarding the differences in GUI demo execution).Crashed
If at any time of execution anErroror anExceptionis thrown from within the demo code, the state changes to CRASHED. The DemoCaseRunnable will then try to calltearDown()in order to exit the demo.3.2.3 GUI Demo Execution
The execution of GUI demos is a little bit more complicated than the execution of standard demos described in the previous sections. This is because usually a demo with graphical output will show a window on the screen. When returning from itsdemo...()method, the window is still visible and the demo should be considered running until the window is being disposed.The DemoCaseRunnable described in the previous sections does not care about that special case. It simply exits the demo by callingtearDown()right after returning from thedemo...()method. So there is a different implementationGuiDemoCaseRunnablenecessary for GUI demos. Figure 3.4 shows a simplified sequence diagram for the execution of an AWT or Swing GUI demo.![]()
Figure 3.4: Sequence diagram of GUI demo execution.
TheGuiDemoCasehas to know what window has been made visible in thedemo...()method. For this theshow(Window)method delegates toregisterDemoWindow(Window). Here theGuiDemoCaseattaches aWindowListenerto the window being shown. Before returning from thedemo...()method, theGuiDemoCasemakes the window object visible. TheGuiDemoCaseRunnableconsiders the demo still being running and does not exit the demo. Once the demo window is being disposed, theWindowListenerof theGuiDemoCasecatches awindowClosing-event and requests theGuiDemoCaseRunnableto exit the demo.
Note that a window object being passed to theregisterDemoWindow(Window)method is called a managed window. Any GUIDemoCaseimplementation should ensure that the window being shown is managed. The sections about the various GUI DemoCases in chapter 4 will explain how to achieve this. Otherwise theGuiDemoCaseRunnablecannot handle state changes correctly. Also other features like changing the LookAndFeel (see section 4.9) and creating screenshots (see section 7.4) will not work.Finally note that for exiting a GUI demo from within the demo code itself (for example when the user hits a button) you can directly call the methodexit()in theGuiDemoCaseclass to dispose the window and exit the demo.
4.1 Choosing an Appropriate Base Class
Depending on what kind of software output you want to demonstrate, you have to choose one of the base classes provided by the framework. Table 4.1 gives a quick overview of what base class you should pick for your demo.
What kind of output shall be demonstrated? Appropriate base class Plain text ( java.lang.CharSequence)de.jdemo.framework.DemoCaseFile objects (e.g. *.html,*.rtf)de.jdemo.framework.DemoCaseDirect output to a hardware device
(e.g. Soundcard, LPT-Port)de.jdemo.framework.PlainDemoCase
Components from the Java AWT
(e.g. java.awt.List)de.jdemo.extensions.AwtDemoCase
Components from Java Swing
(e.g. javax.swing.JTable)de.jdemo.extensions.SwingDemoCase
Components from the IBM Eclipse SWT de.jdemo.extensions.SwtDemoCase
Table 4.1: Base classes to choose for various purposes
Each of the base classes provides convenience methods for demo implementations. They are described in the following sections and in the JDemo JavaDoc API.4.2 Class Hierarchie
Figure 4.1 shows the inheritance hierarchie of all demo case base classes provided with JDemo. Along with the base classesPlainDemoCaseandDemoCase(for showing files and plain text), there are three gui demo case classesAwtDemoCase,SwingDemoCaseandSwtDemoCase. All those classes are described in the following sections.![]()
Figure 4.1: Inheritence hiearchie of the DemoCase base classes in JDemo
4.3 AbstractDemoCase
AbstractDemoCaseis the abstract base class for all demo case implementations. It contains basic implementations and convenience methods. You will not have to care about this class, unless you want to implement a new type of demo case base class.4.3.1 API Description
protected void exit();
This method can be called from inside a
IDemoCaseto send a request to theIDemoCaseRunnableto exit the running demo. As for now calling this method only makes sense for GUI demo cases. This has been described in section 3.2.3.
public void cancel();
This method will be called from the DemoCaseRunnable to send a request to the
IDemoCaseto cancel its execution. Subclasses can overwrite this method in order to e.g. dispose a window. This method should not be called from inside a demo method itself.
4.4 PlainDemoCase
PlainDemoCaseis the most simple implementation of theIDemoCaseinterface. It only implements the methods already described in the previous sections.You should choose this class as superclass for your demo if the output of your demo does not belong to the ones supported by the other base classes described below. This is most likely the case if your demo makes output directly to a hardware device like a soundcard, a printer or a robot connected to the serial port.4.4.1 Example Usage
Here is an example of aPlainDemoCasedemo playing a simple sound using theToolkit.beep()method from AWT:
public class PlainDemoCaseUsageDemo extends PlainDemoCase {
public void demoToolkitBeep() throws Exception {
Toolkit.getDefaultToolkit().beep();
Thread.sleep(500);
Toolkit.getDefaultToolkit().beep();
}
}4.5 DemoCase
DemoCaseis another implementation of theIDemoCaseinterface. It provides convenience methods that can be used in demo implementations for showing files and plain text:![]()
4.5.1 API Description
protected File createTempFile(String suffix);
This convenience method creates a temporary file with the given suffix (=file name extension, e.g. ".txt"). The file will be deleted when the virtual machine terminates.
protected void show(File file);
Tries to open the given file by passing it to the operating system. This is useful for example if the output of the demo is a *.html file or any other kind of binary. The method passes the file's name to the operating system which hopefully will open the file using the default application.
Note that this might not work properly on some systems. In fact at the moment it only has been implemented for Windows systems. The implementation for file launching can be found in
de.jdemo.util.FileLauncher.
protected void show(CharSequence text);
Shows the given text (
java.lang.Stringimplements thejava.lang.CharSequenceinterface). By default the text is printed toSystem.out. The Swing based demo runner however shows the text in a dialog window instead.
4.5.2 Example Usage
In the examples directory of the JDemo distribution there is a classde.jdemo.examples.DemoCaseUsageDemocontaining example demos using theDemoCaseAPI. Here is an excerpt from this file:
public class DemoCaseUsageDemo extends DemoCase {
/**Demo creating a temporary file and opening it using the convenience method.*/
public void demoShowFile() throws IOException {
File file = createTempFile(".html");
BufferedWriter bw = new BufferedWriter(new FileWriter(file));
bw.write("<html><head></head><body>");
bw.write("<h1>Demo file created from within a JDemo demonstration program</h1>");
bw.write("</body></html>");
bw.close();
show(file);
}
/**Demo showing textual output.*/
public void demoShowText() {
show("Hello World");
}
}4.6 GuiDemoCase
GuiDemoCaseis the superclass class forAwtDemoCaseandSwingDemoCase. It only provides methods for managingWindowobjets. Those methods are required by both subclasses and by the GUI capturing code described in chapter 7.![]()
4.6.1 API Description
protected void registerDemoWindow(Window window);
Registers the given window as demo window for this GuiDemoCase. Usually called by any framework method that displays a window object.
Note that all
public Window getRegisteredDemoWindow();
Returns the demo window registered with this GuiDemoCase or
nullif there is none registered.
show...()methods in the sublasses ofGuiDemoCaseensure that the displayed objects are contained in a registered window. So you will not have to care for registering your component yourself.4.7 AwtDemoCase
![]()
4.7.1 API Description
protected void show(CharSequence text);
Convenience method for showing the given text in a
java.awt.TextAreacomponent using a fixed width font.
protected void showProportional(CharSequence text);
Convenience method for showing the given text in a
java.awt.TextAreacomponent using a proportional font.
protected void show(Component component);
Convenience method for showing any kind of
java.awt.Componentobject.
protected void show(Component[] components, LayoutManager layout);
Convenience method for showing an array of
java.awt.Componentobjects. The specified layout manager will be used to lay out the components.
protected void show(Window window);
Convenience method for showing any kind of
java.awt.Windowobject. The given object will also be registred as demo window for this democase (if not being registered already). Note that the window will be packed, centered on the screen and made non-modal if being a dialog.
protected void showAsIs(Window window);
Convenience method for showing any kind of
java.awt.Windowobject. The given object will also be registred as demo window for this democase (if not being registered already). Note that the window will be made non-modal if being a dialog.
protected Frame createFrame();
Convenience method for creating a new
java.awt.Frameobject that can be used for demo implementations. The frame is automatically registered as demo window and decorated with the necessary window listener, icon, title, etc.
protected void setFrameTitle(String title);
Sets the title for the frame being created by this demo case. Setting it to
null(default) will set the title to the name of the demo.
protected void setFrameIconImage(Image icon);
Sets the image that will be used for the frame icon when showing this demo.
4.7.2 Example Usage
In the examples directory of the JDemo distribution there is a classde.jdemo.examples.awt.AwtDemoCaseUsageDemocontaining example demos using theAwtDemoCaseAPI. Have a look at its commented source code in order to see proper usage of the API.4.8 SwingDemoCase
AsSwingDemoCaseis a subclass ofAwtDemoCaseyou can use all of its convenience methods. In addition it provides Swing specific methods.![]()
4.8.1 API Description
protected void show(CharSequence text);
Convenience method for showing the given text in a
javax.swing.JTextPanecomponent using a fixed width font.
protected void showProportional(CharSequence text);
Convenience method for showing the given text in a
javax.swing.JTextPanecomponent using a proportional font.
protected void show(JComponent component);
Convenience method for showing any kind of
javax.swing.JComponentobject.
protected void show(Icon icon);
Convenience method for showing a
javax.swing.Iconobject.
protected void show(Icon[] icons, LayoutManager layout);
Convenience method for showing an array of
javax.swing.Iconobjects. The specified layout manager will be used to lay out the icons.
protected void show(Image image);
Convenience method for showing a
java.awt.Imageobject.
protected void show(Image[] images, LayoutManager layout);
Convenience method for showing an array of
java.awt.Imageobjects. The specified layout manager will be used to lay out the images.
protected void show(JPopupMenu popupMenu);
Convenience method for showing a popup menu. The menu will be "embedded" into a frame.
protected JFrame createJFrame();
Convenience method for creating a new
javax.swing.JFrameobject that can be used for demo implementations.
protected void setFrameIcon(Icon icon);
Sets the icon that will be used for the frame when showing this democase.
4.8.2 Example Usage
In the examples directory of the JDemo distribution there is a classde.jdemo.examples.jfc.SwingDemoCaseUsageDemocontaining example demos using theSwingDemoCaseAPI. Have a look at its commented source code in order to see proper usage of the API.4.9 LookAndFeel with SwingDemoCases
Usually setting the LookAndFeel is being done by a call to a static method in thejavax.swing.UIManagerclass. However for demos this is not good practice, since we would then have to implement multiple demos of the same component in order to see it in various LookAndFeels. To avoid this problem demos are subject to the following restrictions:Setting the preferred LookAndFeel can be done by calling one of the convenience methods provided by the
- Any demo implementation can set its preferred LookAndFeel in the setup method or at the beginning of the demo method.
- Users must be able to optionally tell the Demo runner what LookAndFeel to use when running a demo. This setting superceedes the preferred LookAndFeel specified in the demo (if any).
- By default demos are run in the Java Cross Platform LookAndFeel.
SwingDemoCaseclass:![]()
4.9.1 API Description
protected void setPreferredLookAndFeel(String lookAndFeelClassName);
Sets the preferred LookAndFeel to the one represented by the given LookAndFeel class name.
protected void setPreferredLookAndFeelCrossPlatform();
Sets the preferred LookAndFeel to the Java Cross Platform LookAndFeel.
protected void setPreferredLookAndFeelGtk();
Sets the preferred LookAndFeel to the Gtk LookAndFeel (
com.sun.java.swing.plaf.gtk.GTKLookAndFeel). Note that this LookAndFeel might not be supported on some systems.
protected void setPreferredLookAndFeelMotif();
Sets the preferred LookAndFeel to the Motif LookAndFeel (
com.sun.java.swing.plaf.motif.MotifLookAndFeel). Note that this LookAndFeel might not be supported on some systems.
protected void setPreferredLookAndFeelSystem();
Sets the preferred LookAndFeel to the system's native LookAndFeel.
Note that using a LookAndFeel not available on your system will result in a
protected void setPreferredLookAndFeelWindows();
Sets the preferred LookAndFeel to the Windows LookAndFeel (
com.sun.java.swing.plaf.windows.WindowsLookAndFeel). Note that this LookAndFeel might not be supported on some systems.
java.lang.ClassNotFoundExceptionor ajava.lang.RuntimeExceptioncausing the demo to fail when being run.4.9.2 Example Usage
In the examples directory of the JDemo distribution there is a classde.jdemo.examples.jfc.LookAndFeelDemocontaining example demos using theSwingDemoCaseLookAndFeel API. Here is an excerpt from this file containing three demos showing aJButtonobject in different LookAndFeels:
Figure 4.7 shows a screenshot of the output from the example.
public class LookAndFeelDemo extends SwingDemoCase {
public void demoSystemLookAndFeel() {
setPreferredLookAndFeelSystem();
show(new JButton("Button in system Look and Feel"));
}
public void demoCrossPlatformLookAndFeel() {
setPreferredLookAndFeelCrossPlatform();
show(new JButton("Button in CrossPlatform Look and Feel"));
}
public void demoMotifLookAndFeel() {
setPreferredLookAndFeelMotif();
show(new JButton("Button in Motif Look and Feel"));
}
}![]()
Figure 4.7: The LookAndFeel demo example showing buttons in different LookAndFeels.
4.9.3 Comments
The default demo runner in JDemo itself uses the system LookAndFeel for its GUI. If there was no other LookAndFeel specified for the demo cases, they also would be rendered using the system LookAndFeel. In order to avoid this, JDemo initializes each Swing demo with the Java Cross Platform LookAndFeel.Since all demos are run in the same virtual machine, it can not be guaranteed that setting the LookAndFeel for one demo does not affect others. This in particular is true when the demo creates new gui components after switching the LookAndFeel, e.g. when creating a new popup window.4.10 SwtDemoCase
The most recent implementedDemoCasesubclass is the one for supporting IBM's windowing toolkit SWT. At the moment it only provides one method:![]()
4.10.1 API Description
protected Shell createShell();
Creates a new
org.eclipse.swt.widgets.Shellobject that can be used for adding widgets. The shell will automatically be made visible when returning from thedemo...()method. Not that calling this method more often than once during execution of a single demo will result in ade.jdemo.framework.exceptions.DemoExecutionFailedError.
4.10.2 Example Usage
In the examples directory of the JDemo distribution there is a classde.jdemo.examples.swt.SwtDemoCaseUsageDemocontaining example demos using theSwtDemoCaseAPI. Here is an excerpt from this file:public class SwtDemoCaseUsageDemo extends SwtDemoCase {Note that for executing SWT demos you must ensure that Java can access the SWT library. Usually this is done by adding the folder containing the SWT libraries to the Java library path using a command like this:
public void demoSwtLabel() {
Label label = new Label(createShell(), SWT.NONE);
label.setText("Hello SWT World!");
}
public void demoExitFromWithinASwtDemoUsingAButton() {
Button button = new Button(createShell(), SWT.PUSH);
button.setText("Exit");
button.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
exit();
}
public void widgetDefaultSelected(SelectionEvent e) {
}
});
}
}-Djava.library.path=D:/java/eclipse/plugins/org.eclipse.swt.win32_3.0.0/os/win32/x86If you want to eliminate the need for specifying the classpath andjava.library.pathoptions in the Java command line you can integrate the SWT JAR and DLL (for Windows) with your Java Runtime Environment (JRE) by copying the jar files to the JRE's lib/ext directory and the DLL to the JRE's bin directory (the same procedure can be applied to other platforms). Refer to the SWT documentation for more detailed information.
5.1 Launching
For launching the Demo Runner you have to run the DemoRunner classde.jdemo.swingui.DemoRunnerand specify the fully qualified name of the demo class or demo suite, that shall be loaded, as argument:Note that both thejava de.jdemo.swingui.DemoRunner org.foo.MyDemojdemo.jar(orjdemo_core.jarandjdemo_runner.jar) and the demo class must be on theCLASSPATH.
If you want the users to be able to browse the demo source code from within the Demo Runner you can specify a source code lookup path using the-sourcepathor-spoption:Similar to the Javajava de.jdemo.swingui.DemoRunner -sp src.zip org.foo.MyDemoCLASSPATH, thesourcepathis a list of directories andziporjarfiles.
For a complete description of the command line parameters of the Demo Runner use this command:java de.jdemo.swingui.DemoRunner -help5.2 Usage
The Demo Runner mainly consists of two parts. In the upper half there is the demo tree and in the lower half there is the demo execution list:![]()
Demos can be started by double clicking them in the demo tree (of course it also works with keyboard navigation). The states of the invoked demos (see section 3.2.2) are shown in the execution list below.
Advanced features are available through the popup menu of the tree:![]()
- Run
Runs the selected demo.- Run with Look&Feel
Runs the selected Swing demo using the Look&Feel (see section 4.9) chosen from the submenu.- Copy demo identifier
Copyies the demo identifier (see section 7.1) of the selected demo to the clipboard. This is useful e.g. if you want to use the demo for automatically capturing its output (see chapter 7).- Show source code
Shows the source code of the selected demo. This item is only enabled if you have specified a source lookup path at startup (see previous section) or are using the Demo Runner from within Eclipse (see chapter 6). Figure 5.3 shows the source code displayed for the hello world demo.- Remove
Removes the selected node from the tree.- Remove duplicates
Removes demos that have the same identifier as others in the tree. This is useful e.g. when you have started the demo runner on a class folder (for example from within an IDE) containing suites and demos. JDemo will then collect both, the demos themselves and all the suites containing the demos.![]()
Figure 5.3: The source code of the Hello World demo displayed in JDemo
The demo execution list has a context menu, too:![]()
- Bring to Front
Brings the window of the selected GUI demo case to front.- Cancel
Cancels the selected demo. Only enabled if the selected demo is running.- Rerun
Reruns the selected demo.- Remove all terminated
Removes all items from the list where the demo state is finished or crashed (see section 3.2.2).
6.1 JDemo Wizards
There are three Wizards for creating demo specific stuff:
- Menu New → Other → Java → JDemo → DemoCase
Creates a new demo case class. You can specify one of the default superclasses (DemoCase,SwingDemoCase,AwtDemoCase, ...).- Menu New → Other → Java → JDemo → DemoSuite
Creates a new demo suite.- Menu New → Other → Java → JDemo → Demo package
Creates a new demo package. This is just a shortcut for creating a new package named "demo".6.2 JDemo Launch Type
There is a new launch type for running demos, providing new launch menu items "Run as JDemo Demonstration" and "Debug as JDemo Demonstration".You can select a DemoCase, a DemoSuite or even a source folder containing demos to be run. The demos are being collected and shown in the Demo Runner.Selecting the context menu item "Show source code" in the Demo Runner will cause Eclipse to open the selected demo and show its source code.6.3 Misc
6.3.1 Recreate Demo Suite
New Context menu item: "Recreate Demo Suite..." for Demo Suites in the Package Explorer. Updates the selected demo suite to the DemoCase implementations in the same folder.6.3.2 Go to Referring Demos
Menu "Navigate → Go To → Referring Demos..." shows a list of all demos for the selected type or method. (This action must be enabled in "Window → Customize Perspective..." )
This chapter has not been finished and will be extended in a future version of this document.
7.1 Demo Identifier
For capturing demo output it is necessary to provide a fully qualifiedStringrepresentation of the demo case. So each demo has a unique identifierDemoIdentifierconsisting of the fully qualified demo class name and the demo method name, separated by a colon. The Hello World demo from section 1.8 for example has the identifierde.jdemo.examples.HelloWorldDemo:demoHelloWorld.7.2 Capturing Textual Output
Capturing the text output from aDemoCaseclass is the most simple option for capturing demo output. The classde.jdemo.capture.text.TextDemoCaptureprovides a simple API for this purpose:
There are two static methods for capturing the output of the demo having the given demo id or the instantiated
public static void captureText(
DemoIdentifier demoId,
Writer writer) throws Throwable;
public static void captureText(
DemoCase demoCase,
Writer writer) throws Throwable;DemoCaseobject. The text output will be written to the specifiedWriterobject.7.3 Capturing File Output
A file created as demo output from within aDemoCaseclass can be copied to a specified file using the classde.jdemo.capture.file.FileDemoCapture:
Again there are two static methods for capturing the file of the demo having the given demo id or the instantiated
public static void captureFile(
DemoIdentifier id,
File outputFile) throws Throwable {
public static void captureFile(
DemoCase demoCase,
File outputFile) throws Throwable {
DemoCaseobject. The file will be copied to the specifiedFileobject.7.4 Making Screenshots
Much more interesting than capturing textual output is to take screenshots from GUI demo cases. The classde.jdemo.capture.gui.GuiDemoCaptureprovides an API that can be used with AWT and Swing DemoCases:
The
package de.jdemo.capture.gui;
public class GuiDemoCapture {
public BufferedImage capture(
DemoIdentifier demoId,
boolean includeFrameTitle)
throws DemoScreenCaptureException, DemoClassNotFoundException;
public void capture(
DemoIdentifier demoId,
boolean includeFrameTitle,
String format,
File file)
throws
DemoScreenCaptureException,
DemoClassNotFoundException,
IOException;
}
GuiDemoCaptureprovides two methods: The first one just creates and returns aBufferedImageobject containing the screenshot. The second one also writes out the image to the specified file using the given image format. Again you need the demo id to qualify the demo case to be captured. With both methods you have the option to only capture the frame contents or to also include its borders.Note that there are increased system requirements for creating screenshots. The current implementation uses thejava.awt.Robotclass from JDK 1.3 for taking the screenshot and the new Java Image I/O Framework provided by Sun since JDK 1.4. Taking screenshots is not possible on systems in headless mode. The supported file formats depend on the imaging plugins being installed on your system. However I recommend to usePNGsince it should be available on any system and most probably fits the needs for screenshots from your program.JPGis another alternative if your program outputs a true color image like a photo for example.Also don't forget to make sure that the display window from your demo is managed (see section 4.6).7.5 Ant Tasks
At the moment one of the standard tools for Java software deployment is Jakarta Ant. As capturing demo output is something that can be very valuable for deployment, JDemo also contains wrapper classes, making capturing available as Ant tasks.7.5.1 Capturing Text Output
The following snippet of an Ant build target defines the new Ant task demoTextCapture and uses it for capturing the output from the Hello World demo:
Running the Ant script should result in a file
<taskdef name="demoTextCapture"
classname="de.jdemo.capture.anttasks.TextDemoCaptureTask"
classpath="jdemo.jar"
/>
<demoTextCapture
demoId="de.jdemo.examples.HelloWorldDemo:demoHelloWorld"
outputFile="captured_text.txt">
<classpath path="."/>
</demoTextCapture>
captured_text.txtbeing created and containing the text "Hello World" as the output from that demo.The Ant task has two properties, described in table 7.1.
Parameter description required demoIdId of the demo to capture the output from yes outputFileFile to write the result to yes
Table 7.1: Properties for the text capture Ant task
7.5.2 Capturing File Output
Capturing a file shown as demo output is just as simple as capturing text. Here is an example Ant code:
Running the Ant script should result in a file
<taskdef name="demoFileCapture"
classname="de.jdemo.capture.anttasks.FileDemoCaptureTask"
classpath="jdemo.jar"
/>
<demoFileCapture
demoId="de.jdemo.examples.FileLauncherDemo:demoShowHtmlFile"
outputFile="captured_file.html">
<classpath path="."/>
</demoFileCapture>
captured_file.htmlbeing created and containing the text html content from the demo.The Ant task has two properties, described in table 7.2.
Parameter description required demoIdId of the demo to capture the output from yes outputFileFile to write the result to yes
Table 7.2: Properties for the filecapture Ant task
7.5.3 Making Screenshots
There is another Ant task available for making screenshots:
Running this Ant script will result in a file
<taskdef name="demoGuiCapture"
classname="de.jdemo.capture.anttasks.GuiDemoCaptureTask"
classpath="..."
/>
<demoGuiCapture
demoId="de.jdemo.examples.dice.demo.MyDiceDemo:demoShowRandomDice"
imageFormat="png"
outputFile="captured_gui.png"
/>
dice6.pngcontaining the screenshot from a die as shown in figure 1.2 (b). The various properties for this Ant task are described in table 7.3.
Parameter description required demoIdId of the demo to capture the output from yes outputFileFile to write the result image to yes imageFormat
The name of the image output format as
defined by the installed imaging library
(e.g.PNG,JPG)no, defaults to
the extension of
the output fileincludeTitle
Flag indicating whether the title of the
output window shall be included in the
screenshot or not (trueorfalse)no, default is true
lookAndFeelClassNameThe name of the look&feel class to be used no
Table 7.3: Properties for the screenshot Ant task
When capturing Swing demos you can specify the look and feel that shall be used by providing thelookAndFeelClassNameparameter. Table 7.4 shows the class names for popular look and feels. For more information about look and feels with demos refer to section 4.9.
Name class name notes Metal javax.swing.plaf.metal.MetalLookAndFeelJava CrossPlatform CDE/Motif
com.sun.java.swing.plaf.motif.MotifLookAndFeel
can be used on
any platformWindows
com.sun.java.swing.plaf.windows.WindowsLookAndFeel
only available on
Microsoft Windows
systemsGTK+ com.sun.java.swing.plaf.gtk.GTKLookAndFeelsince JDK1.4.2 Mac com.sun.java.swing.plaf.mac.MacLookAndFeel
Table 7.4: Popular look&feels
7.5.4 Known limitations
Taking screenshots is a non trivial job, so there are some things you have to take care of:
- If the demo code starts threads of its own influencing the GUI, screenshots taken by JDemo might not be complete. Make sure that such code is rather processed on the event dispatch thread. For example consider using
javax.swing.SwingUtilities.invokeLater(Runnable).- If the demo shows an animation the result of the screencapture is indeterministic. If the animation takes a lot of CPU time the capture might fail with a timeout, since there is a quiet period on the event dispatch thread required.
- Don't open or move other windows on your desktop while screencapture takes place. Screencapture really takes screenshots and it will grabb whatever window covers the actual demo.
7.6 Image processings
Some screenshots require image processings before the images fit the requirements for the web or for other documents. As an experimental feature the JDemo project contains a few Ant tasks for such kind of image processings. Since they actually work independent of JDemo, it is likely that I will move those tasks to a separate project soon.7.6.1 Generic image processings
There is a generic Ant taskImageProcessingTaskthat can be used for applying a sequence of processings to an image. At present, scaling is the only processing implemented. Here is an example that reads the filescreenshot.png, scales the image to a width of 200 pixels using a smooth scaling algorithm and writes the resulting image to the filescreenshot_small.png:
Table 7.5 describes the parameters of the
<taskdef name="imageProcessing"
classname="de.jave.image.ant.ImageProcessingTask"
classpath="${classpath}"
/>
<imageProcessing
srcFile="screenshot.png"
outputFile="screenshot_small.png">
<rescale width="200"qualityHint="smooth"/>
</imageProcessing>
ImageProcessingTaskand table 7.6 describes the parameters of its nested elementrescale.
Parameter description required srcFileFile to read the original image from yes outputFileFile to write the result image to yes imageFormat
The name of the image output format as
defined by the installed imaging library
(e.g.PNG,JPG)no, defaults to
the extension of
the output file
Table 7.5: Parameters for the image processing Ant task
Parameter description required width
The width of the result in pixels or as percentage
of the original image.
(e.g.800,75%)Exactly one of width
orheightmust be
specified.height
The height of the result in pixels or as percentage
of the original image.
(e.g.800,75%)Exactly one of width
orheightmust be
specified.qualityHint
Rescale filter as defined by the java.awt.Image
class. Valid values are:Smooth,AreaAveraging,
Default,ReplicateandFastno, default is Smooth
Table 7.6: Parameters for the nested rescale processing
7.6.2 Composing images
TheImageCompositionTaskloads images from multiple files and arrages them to a new image. The size of the result image is the maximum extent of all positioned images. This task was used to create figure 4.7, which is a composition of four images captured using JDemo. Here is the source code from the Ant build script:
Table 7.7 describes the parameters of the
<taskdef name="imageComposition"
classname="de.jave.image.ant.ImageCompositionTask"
classpath="${classpath}"
/>
<imageComposition
backgroundColor="FFFFFF"
outputFile="${screenshot.dir}/lookandfeelbuttons.png">
<image file="${tmp.dir}/laf_jdemo.png"x="0"y="0"/>
<image file="${tmp.dir}/laf_system.png"x="296"y="26"/>
<image file="${tmp.dir}/laf_crossplatform.png"x="269"y="95"/>
<image file="${tmp.dir}/laf_motif.png"x="296"y="169"/>
</imageComposition>
ImageCompositionTaskand table 7.8 describes the parameters of its nested elementimage.
Parameter description required outputFileFile to write the result image to yes imageFormat
The name of the image output format as
defined by the installed imaging library
(e.g.PNG,JPG)no, defaults to
the extension of
the output filebackgroundColor
The background color of the image to be created
as six-digit hexadecimal rgb valueNo, default is FFFFFF
Table 7.7: Parameters for the image composition Ant task
Parameter description required fileFile to read the original image from yes xThe x position to add the image at no, default is 0yThe y position to add the image at no, default is 0
Table 7.8: Parameters for the nested image element
Note that this Ant task could also be used for adding mouse cursors or other transparent images to decorate screenshots.
8.1 Automated conversion from demos to tests
The classde.jdemo.junit.Demo2TestConvertercreates a JUnit testcase (or testsuite) from the given democase (or demosuite):
public static Test createTest(IDemo demo);The created unit test runs the demo and cancels it immediately. It fails if there is a
java.lang.Throwablethrown during this procedure. It also stops with a timeout error if returning from the demo method takes very long. You can either use the default timeout value (30000ms in the current implementation of the framework) or specify the number of milliseconds when creating the test:
public static Test createTest(IDemo demo, long timeOutMillis);By using the methods above you can easily add demos to your suite of unit tests. You only have to add a single line of code to your main test suite:
public class AllTests {This code converts all demos contained in the main demo suite
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTest(Demo2TestConverter.createTest(AllDemos.suite()));
//add other test suites...
return suite;
}
}
AllDemosto tests and adds them to the suite of tests.8.2 Peculiarities with demo-tests
There is one peculiarity when executing tests based on demos that show a file using theshow(File)method in theDemoCaseclass: The file is not being shown in an external browser but instead it is only being checked whether the file exists. If it does not exist, the test fails.8.3 Evaluation
Tests created from demos are nothing more than smoke tests. They only fail when something goes terribly wrong but by no means guarantee that the demo does what it should.However on the other hand those demo-tests are for free, and by ensuring that all demos can be executed, they will help you to prevent some of the most embarrassing kind of bugs in demo code. So all in all I think its worth using them.
9.1 JDemo Annotation
The JDemo annotation is defined as follows:
The annotation contains two optional elements:
package de.jdemo.annotation;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface JDemo {
public String description() default"";
public String[] categories() default {};
}
- A description text in HTML format, that may describe the details of the demo. The description for a demo can then be accessed from the Demo Runner application and be presented to the user.
- An array of strings in order to assign the demo to certain categories. Categories may be used by demo runner applications e.g. for filtering demos.
9.2 Example
Here is a simple example using the JDemo annotation feature:
The example adds a HTML description to the demo method and assigns it to the categories
@JDemo(
description ="<h1>Hello World</h1><p>Prints "Hello World!".</p>",
categories = {"example","public"}
)
public void demoHelloWorld() {
show("Hello World!");
}
exampleandpublic. Note that there are no predefined categories in the framework.The JDemo Demo Runner can be configured to show descriptions from annotations in an additional panel on the right (Use the View menu to adjust this setting):![]()
10.1 JDemo CVS
The source code of the complete JDemo framework is contained in the download package. You can also access the most current version from the SourceForge CVS (http://sourceforge.net/projects/jdemo/). There you will have to check out the following projects:
Project Contents JDemo The core project for the framework JDemo_build Build script for compilation and deployment JDemo_swingrunner The Swing based demo runner application JDemo_examples The examples JDemo_thirdparty Thirdparty libraries required for JDemo and deployment JDemo_tiger JDK 1.5 (Tiger) related classes e.g. for Annotations JDemo_imageprocessing Image processing code for screen capture and Ant tasks JDemo_eclipse
Eclipse plugin for Eclipse 3.0/3.1
(there also is a branch for the 2.1 version)
The JDemo_eclipse and JDemo_examples projects are optional. In order to build JDemo you can use the Ant build script from the JDemo_build project. For a full build you will need both a JDK1.4 and a JDK1.5 compiler. You must specify the paths to your compilers by creating a properties filesystem_dependent_build.properties. There is a template for this file in the build project.10.2 Writing your own DemoRunner
Unless you have a very brillant idea for a new demo runner, I recommend contributing to the existing one. However if you want to write your own runner you are welcome to do so, too. Look at the source code of the original demo runner to get an idea of how to build the tree etc. Some utility methods for instantiating a demo can be found in the classde.jdemo.framework.util.DemoUtilities. Once you have an instancemyDemoof a JDemo demo you can launch using code somewhat like this:
IDemoCaseRunnable runnable = myDemo.createRunnable();
runner.addDemoStateChangeListener(new IDemoStateChangeListener() {
public void demoStateChanged(IDemoStateChangeEvent event) {
//Do whatever appropriate for the state change happened
}
});
new Thread(runnable).start();
10.3 Integrating the DemoRunner into other Applications
At the moment Eclipse is the only IDE supporting JDemo by a plugin (see chapter 6). Supporting other development environments should not be hard to be done. The wizards for creating demo cases and suites can be implemented similar as the existing ones for JUnit support. Launching demos should be done by launching the existing Runner. Feel free to ask me if you have any questions about this.
11.1 Batch Capture
An additional Ant task for capturing complete suites instead of single demos (see chapter 7) would be nice. Also optionally a Html page should be created, containing the captured images (or links to captured files).11.2 Executing Sequences of Demos
JDemo demos are unit demos: one demo case can only demonstrate a single unit - either a dialog or an exported file, for example, but not both together. In some situations I would like to be able to connect multiple demos to a more complex scenario.
Example: Given we have two demos, one that displays a dialog for entering information, and a second one for demonstrating some kind of file export. The file export works with some demonstration data, but would also work with the information that has been entered in the first demo. In this situation I would like to be able to (optionally) connect both demos, so that the user can enter the data in the dialog and also sees the exported file afterwards.
I do not yet have any idea about how to make this work. On the other hand I am also not really sure if I want to allow such complex kind of interaction. The power of JDemo is its simplicity and I cannot imagine a simple solution here. However any kind of ideas or comments are welcome.
|
Converted from PDFLaTeX to HTML 2005-01-08 using PDFLaTeX2Html 1.0 |
|