blob: dab206c0132fed666fe6c88a75c8d11efa96f215 [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Automating Eclipse PDE Unit Tests using Ant</title>
<link href="../article.css" rel="stylesheet" type="text/css">
<body>
<h1>Automating Eclipse PDE Unit Tests using Ant</h1>
<div class="summary">
<h2>Summary</h2>
<p>This article outlines how to integrate your PDE unit tests into
an Ant based automated build, using a simple Eclipse plug-in as an
example, some simple java classes, basic Eclipse plug-in techniques and
some standard Ant tasks.</p>
<div class="author">By Brian Joyce, <a target="_blank"
href="http://www.duolog.com">Duolog Technologies Ltd., Galway,
Ireland</a></div>
<div class="copyright">Copyright &copy; 2008, Brian Joyce</div>
<div class="date">June 13, 2008</div>
</div>
<div class="content">
<h2><a name="Introduction"></a>Introduction</h2>
<p>It's generally accepted that writing tests as part of software
development is a very good thing indeed. It's also generally accepted
that automating the running of tests in an automated or nightly build is
good engineering practice. Let's face it, if tests are not run
automatically then there's a good chance they won't be run at all, and
tests that are not run are next to useless.</p>
<p>The Eclipse Plug-in Development Environment (PDE) provides a
excellent framework for developing plug-ins and also provides facilities
to write and run PDE unit tests for your plug-ins that can be run from
within the Eclipse environment.</p>
<p>Once you have taken the time and effort to write these valuable
PDE unit tests, how do you automate the running of these PDE unit tests
so that you can integrate them into your automated build?</p>
<p>Searching the web provides several options for automating PDE
tests such as: </p>
<ul>
<li>Markus Barchfeld's excellent <a
href="http://www.eclipse.org/articles/Article-PDE-Automation/automation.html"
target="_blank">Build and Test Automation for plug-ins and
features</a> article which details setting up automatic building and
testing for an Eclipse plug-in using the Eclipse headless build.</li>
<li><a
href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.test/testframework.html?view=co"
target="_blank">Eclipse Test Framework</a>.</li>
<li>Patrick Paulin's RCP Quickstart post on <a
href="http://rcpquickstart.wordpress.com/2007/08/06/running-automated-tests-with-pde-build/"
target="_blank">Running Automated Tests with PDE Build.</a></li>
<li>Some more excellent links can be found at <a
href="http://eclipsenuggets.blogspot.com/2007/09/6-great-links-for-eclipse-build.html"
target="_blank">6 Great Links for Eclipse Build Automation with
PDE Build</a>.</li>
</ul>
<p>As you can see writing PDE Tests can be complex, running PDE
Tests from the command line can be complex too, but running them and
collecting the results in a format that can be easily interpreted (e.g.
Junitreport format) is even more difficult.</p>
<p>This article provides a detailed example application, the
enabling technology to collect and format test results (see <a
href="#PDE_Test_Utilities">PDE Test Utilities</a> ), and a build system
that demonstrates a generic mechanism for running PDE Tests using Ant,
allowing you to integrate it with any Ant build system.</p>
<p>This PDE Test technique provides the following benefits:</p>
<ol>
<li>Allows you to run your PDE Tests from the command line</li>
<li>Allows you to collect the PDE Tests results in a format that
can be easily interpreted (i.e. Junitreport format)</li>
<li>Allows you to integrate PDE Tests into any Ant-based build
system</li>
</ol>
<p><strong>Note:</strong> all the techniques and examples detailed
in this article have been tested against Eclipse 3.3 (specifically
Eclipse 3.3.2 and 3.3.1.1) on Windows XP only and using <a
href="http://ant.apache.org/bindownload.cgi" target="_blank">Ant
1.7.0</a> . There is also an <a href="PDETestExampleProjects-3.1.zip">Eclipse
3.1 version</a> of the example code.</p>
<h2><a name="Overview"></a>Overview</h2>
<p>PDE unit tests are automated as follows:</p>
<h3>Prerequisites:</h3>
<ol>
<li>A dedicated PDE test Eclipse installation that is only used by
the automated build system.</li>
<li>For each Eclipse plug-in <i style="color: rgb(255, 0, 0);">A</i>
that is to be tested, an Eclipse plug-in fragment <i
style="color: rgb(255, 0, 0);">A-test</i> for <i
style="color: rgb(255, 0, 0);">A</i> that only contains the PDE unit
tests and their test dependencies for the plug-in <i
style="color: rgb(255, 0, 0);">A</i>.</li>
<li>A pre-defined (or specified) PDE test port.</li>
<li>A PDE test listener class to listen on the PDE test port for
the results from the PDE test run.</li>
<li>A list of PDE test classes to be run as part of the PDE Test
run</li>
</ol>
<h3>Running the PDE unit tests:</h3>
<p>See <a href="#Figure_1_-_Overview_diagram_of_the_PDE">Figure 1</a>
below for a visual representation of the PDE test steps.</p>
<ol>
<li>Deploy plug-in <i style="color: rgb(255, 0, 0);">A</i> and
plug-in fragment <i style="color: rgb(255, 0, 0);">A-test</i> into a
pristine PDE test Eclipse installation.</li>
<li>Select PDE test port (or use predefined reserved port).</li>
<li>Start the PDE test listener process that listens on the PDE
test port.Startup the PDE test Eclipse installation, specifying the
list of unit test classes to be run, and the PDE test port to output
test progress and results to.</li>
<li>The PDE test Eclipse installation starts up and automatically
runs the specified tests and outputs the results to the PDE test port
where the PDE test listener process captures the results and outputs
them in standard Ant <a target="_blank"
href="http://ant.apache.org/manual/OptionalTasks/junit.html">junit</a>
task XML format.</li>
<li>Run the regular Ant <a target="_blank"
href="http://ant.apache.org/manual/OptionalTasks/junitreport.html">junitreport</a>
task on the generated test results XML files.</li>
<li>That's it: you now have a typical Ant JUnit HTML report
containing your PDE unit test results.</li>
</ol>
<div class="figure"><a name="Figure_1_-_Overview_diagram_of_the_PDE"></a><img src="images/PDETestProcessFlow.jpg"
style="border: 2px solid; width: 1121px; height: 610px;"
alt="PDE Test process flow diagram"
title="PDE Test process flow diagram">
<p class="caption">Figure 1 - Overview diagram of the PDE Test steps</p></div>
<h2>Prerequisites</h2>
<p>This section describes the prerequisites for using this technique
in more detail.</p>
<h3>Dedicated PDE test Eclipse installation</h3>
<p>In order to run the PDE Tests you need a separate Eclipse installation
whose sole purpose is for running the PDE Tests. Having a dedicated
Eclipse installation provides a pristine and repeatable test environment
and avoids any possible conflicts or corruption that might occur with a
typical development Eclipse installation. </p>
<h3>Use an Eclipse plug-in fragment for the PDE Unit Tests for a
plug-in</h3>
<p>This technique promotes the use of <a
href="http://help.eclipse.org/help33/topic/org.eclipse.platform.doc.isv/guide/product_def_plugins.htm"
target="_blank">Eclipse plug-in fragments</a> to develop PDE Unit tests
for plug-ins, so for each Eclipse plug-in <i
style="color: rgb(255, 0, 0);">A</i> that is to be tested, an Eclipse
plug-in fragment <i style="color: rgb(255, 0, 0);">A-test</i> for <i
style="color: rgb(255, 0, 0);">A</i> that only contains the PDE unit
tests and their test dependencies for the plug-in <i
style="color: rgb(255, 0, 0);">A</i>.</p>
<p>You can of course develop the PDE tests directly in the plug-in
(in a test directory), but this can lead to unwanted dependencies in
your plug-in and involves slightly more complicated packaging for
your plug-in (i.e. without test classes and test dependencies).</p>
<p>The Eclipse plug-in fragment approach avoids these
pitfalls and although it requires a little more setup initially it
provides a cleaner and clearer mechanism for defining PDE Tests and also
provides a straightforward way for the build system of identifying which
plug-ins have PDE Tests associated with them.</p>
<p>For a good description and more general discussion of using
Eclipse plug-in fragments for testing, see Patrick Paulin's RCP
Quickstart article <a
href="http://rcpquickstart.wordpress.com/2007/06/20/unit-testing-plug-ins-with-fragments/"
target="_blank">Testing Plug-ins with Fragments</a>.</p>
<h3>PDE test port</h3>
<p>In order for the PDE test runner and the PDE test listener
processes to communicate, both processes need to use a predefined or
specified port so that the PDE test runner can send the test progress
and results to the PDE test listener process. In the example code
we use a utility class <a href="#PDETestPortLocator"><code>pde.test.utils.PDETestPortLocator</code></a>
in the <a href="article.html#PDE_Test_Utilities">pde.test.utils</a>
plug-in to find an available port and this is used by the PDE test runner
and PDE test listener processes to communicate.</p>
<h3>PDE test listener process</h3>
<p>In order to be able to monitor and record the progress
and results of the PDE test run, you need a PDE test listener
process that listens on the specified port to collect PDE test progress
and results from the PDE test runner process. Ideally the PDE test
listener process should provide the results of the PDE test run in a
manner that is easy to interpret should any of the tests fail.</p>
<p>The <a href="#PDETestResultsCollector"><code>pde.test.utils.PDETestResultsCollector</code></a>
class (using the <a href="#PDETestListener"><code>pde.test.utils.PDETestListener</code></a>
class) in the <a href="article.html#PDE_Test_Utilities">pde.test.utils</a>
plug-in, provides the PDE test listener process that listens on the
specifed port for test results from the PDE test runner process and
handles them using the <code>org.apache.tools.ant.taskdefs.optional.junit.JUnitTest</code>
and <code>org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter</code>
classes (available from Apache Ant API) to provide the results in the
same XML format that is output by the Ant <a target="_blank"
href="http://ant.apache.org/manual/OptionalTasks/junit.html">junit</a>
task. These XML result files can then be used by the Ant <a
target="_blank"
href="http://ant.apache.org/manual/OptionalTasks/junitreport.html">junitreport</a>
task to provide an <a href="reports/test/index.html">HTML report</a> of
the PDE test run that is very easily interpreted.</p>
<p>For example to run the PDE test listener process from the command
line for our example PDE tests would similar to:</p>
<pre> java -classpath ... pde.test.utils.PDETestResultsCollector PhoneBookExample-test 1623</pre>
<h3>PDE test runner process</h3>
<p>Eclipse provides a mechanism for running tests from the command
line using the main Eclipse launcher class to launch the <code>org.eclipse.pde.junit.runtime.uitestapplication</code>
application, this is the PDE test runner process. The PDE test runner
process is passed details of the port to publish test progress and
results to for listeners to analyse, the plug-in name being tested and
the names of the PDE test classes to run.</p>
<p>For example to run the PDE test runner process from the command
line for our example PDE tests would similar to:</p>
<pre>java -classpath ...\eclipse\plugins\org.eclipse.equinox.launcher_1.0.1.R33x_v20080118.jar
org.eclipse.equinox.launcher.Main
-application org.eclipse.pde.junit.runtime.uitestapplication
-data ...\PhoneBookExample-test\target\reports\test/output/ws
-dev bin
-clean
-port 1623
-testpluginname PhoneBookExample
-classnames phonebookexample.dialogs.PhoneBookEntryEditorDialogTest</pre>
<h3>PDE Tests classes list</h3>
<p>The PDE test runner process takes as a parameter a comma
separated list of the test classes to run in a PDE test run. In the
example code, the name of the single test class to be
run is hardcoded i.e. <code>phonebookexample.dialogs.PhoneBookEntryEditorDialogTest</code>
but the generation of the list of PDE test classes could easily be
automated.</p>
<h2>Running PDE Unit Tests in Ant</h2>
<p>This section describes the Ant build file in the example code
that runs the PDE Tests and explains the key Ant targets involved. See <a
href="article.html#Figure_1_-_Overview_diagram_of_the_PDE">Figure 1</a>
above for a visual representation of the steps involved in running PDE
tests in Ant.</p>
<p>The example code featuring full source and Ant build files
for a project containing PDE unit tests can be found in the
accompanying <a href="PDETestExampleProjects-3.3.zip">PDETestExampleProjects-3.3.zip</a>
ZIP file.</p>
<p><strong>Note:</strong> that the <a
href="PDETestExampleProjects-3.3.zip">PDETestExampleProjects-3.3.zip</a>
ZIP file contains a full standalone project complete with an Ant
build system (see <a
href="article.html#PDETestExampleProjects.zip_Contents">zip
contents</a> below for more details). Unzip the contents into
a directory that is separate from your Eclipse installation and workspace.</p>
<h3>Ant script that runs PDE Unit tests</h3>
<p>The following Ant excerpt is from the Ant build file used to run
the PDE unit tests in the <i>PhoneBookExample-test</i> plug-in fragment
for the <i>PhoneBookExample</i> plug-in (see <i>projects\PhoneBookExample-test\build.xml</i>
in the accompanying ZIP file):</p>
<pre>&lt;!-- Build file for the Phonebook Example plug-in PDE unit test fragment --&gt;
&lt;project name="phonebookexampletest" default="help" basedir="."&gt;
...
&lt;target name="pde_test"&gt;
<img src="images/tag_1.gif" align="middle" height="13" width="24"> &lt;delete&gt;
&lt;fileset dir="${test.eclipse.dir}/configuration" includes="**/*" excludes="config.ini"/&gt;
&lt;fileset dir="${test.eclipse.dir}/plugins" includes="PhoneBookExample*.jar"/&gt;
&lt;fileset dir="${test.eclipse.dir}/plugins" includes="pde.test.utils*.jar"/&gt;
&lt;/delete&gt;
&lt;!-- Load plugin and pde tests plugin fragment into test eclipse installation --&gt;
<img src="images/tag_2.gif" align="middle" height="13" width="24"> &lt;copy todir="${test.eclipse.dir}/plugins" overwrite="true"&gt;
&lt;fileset dir="${published.plugins.dir}"/&gt;
&lt;/copy&gt;
&lt;delete file="pde_test_port.properties"/&gt; &lt;!-- properties file generated by PDETestPortLocator class in pde.test.utils --&gt;
<img src="images/tag_3.gif" style="width: 24px; height: 13px;"
align="middle"> &lt;java classname="pde.test.utils.PDETestPortLocator" fork="yes" classpathref="pde.test.port.locator.class.path"/&gt;
&lt;waitfor maxwait="10" maxwaitunit="second" checkevery="100" checkeveryunit="millisecond"&gt;
&lt;available file="pde_test_port.properties"/&gt;
&lt;/waitfor&gt;
&lt;property file="pde_test_port.properties"/&gt;
&lt;echo message="Using port ${pde.test.port} for listening to PDE Test run"/&gt;
&lt;parallel&gt;
&lt;daemons&gt;
<img src="images/tag_4.gif" align="middle" height="13" width="24"> &lt;antcall target="run_pde_test_listener"/&gt;
&lt;/daemons&gt;
&lt;sequential&gt;
&lt;sleep seconds="5"/&gt; &lt;!-- Give the listener a few seconds to start up --&gt;
<img src="images/tag_5.gif" align="middle" height="13" width="24"> &lt;antcall target="run_pde_tests"/&gt;
&lt;/sequential&gt;
&lt;/parallel&gt;
<img src="images/tag_6.gif" align="middle" height="13" width="24"> &lt;delete&gt;
&lt;fileset dir="${test.eclipse.dir}/plugins" includes="PhoneBookExample*.jar"/&gt;
&lt;fileset dir="${test.eclipse.dir}/plugins" includes="pde.test.utils*.jar"/&gt;
&lt;/delete&gt;
&lt;mkdir dir="${test.reports.dir}"/&gt;
<img src="images/tag_7.gif" align="middle" height="13" width="24"> &lt;move todir="${test.reports.dir}"&gt;
&lt;fileset dir="."&gt;
&lt;include name="**/TEST-*.xml"/&gt;
&lt;/fileset&gt;
&lt;/move&gt;
&lt;/target&gt;
<img src="images/tag_4.gif" align="middle" height="13" width="24"> &lt;target name="run_pde_test_listener"&gt;
&lt;java classname="pde.test.utils.PDETestResultsCollector" fork="yes" classpathref="pde.test.listener.class.path"&gt;
&lt;arg line="${plugin.name} ${pde.test.port}"/&gt;
&lt;/java&gt;
&lt;/target&gt;
<img src="images/tag_5.gif" align="middle" height="13" width="24"> &lt;target name="run_pde_tests"&gt;
&lt;property name="test.classes.list" value="phonebookexample.dialogs.PhoneBookEntryEditorDialogTest"/&gt;
&lt;mkdir dir="${test.reports.dir}/output/ws"/&gt;
&lt;java dir="${plugin.dir}" classname="org.eclipse.equinox.launcher.Main" fork="yes" classpathref="equinox.launcher.class.path"&gt;
&lt;arg line="-application org.eclipse.pde.junit.runtime.uitestapplication -data ${test.reports.dir}/output/ws -dev bin -clean -port ${pde.test.port} -testpluginname PhoneBookExample -classnames ${test.classes.list}"/&gt;
&lt;/java&gt;
&lt;/target&gt;
...
&lt;/project&gt;</pre>
<p>The key elements of this Ant build file are identified above:</p>
<table cellpadding="2" cellspacing="2">
<tbody>
<tr>
<td style="width: 10%;"><img src="images/tag_1.gif"
align="middle" height="13" width="24"></td>
<td style="width: 90%;">This prepares for the PDE test run by
deleting all previously deployed plug-ins from the plugins directory
of the dedicated test installation of Eclipse.</td>
</tr>
<tr>
<td style="width: 10%;"><img src="images/tag_2.gif"
align="middle" height="13" width="24"></td>
<td style="width: 90%;">This copies the set of plug-ins under
test (including the test fragment) into the plugins directory of the
test installation of Eclipse.</td>
</tr>
<tr>
<td style="width: 10%;"><img src="images/tag_3.gif"
align="middle" height="13" width="24"></td>
<td style="width: 90%;">This discovers an available port for the
PDETestListener to listen on - it does it by launching a simple java
class (PDETestPortLocator) to detect the next available port and
stores it as a property pde.test.port in the pde_test_port.properties
file. This property is then loaded from the pde_test_port.properties
file and is used in the test run.</td>
</tr>
<tr>
<td style="width: 10%;"><img src="images/tag_4.gif"
align="middle" height="13" width="24"></td>
<td style="width: 90%;">This step launches the PDETestListener
in a separate thread (using the Ant parallel &amp; daemons tasks) to
listen for test results on the port identified by the pde.test.port
property (see Label 3 above)</td>
</tr>
<tr>
<td style="width: 10%;"><img src="images/tag_5.gif"
align="middle" height="13" width="24"></td>
<td style="width: 90%;">This is the actual step that runs the
PDE Unit tests and specified that the results should be published to
a listener using the port identified by the pde.test.port property
(see Label 3 above).<br>
Note: that the list of test classes needs to be specified for the
test run, this can easily be automatically generated.</td>
</tr>
<tr>
<td style="width: 10%;"><img src="images/tag_6.gif"
style="width: 24px; height: 13px;" align="middle"></td>
<td style="width: 90%;">After the PDE test run the test
installation of Eclipse is cleaned up by deleting all the deployed
plug-ins from the plugins directory.</td>
</tr>
<tr>
<td style="width: 10%;"><img src="images/tag_7.gif"
align="middle" height="13" width="24"></td>
<td style="width: 90%;">Copy the test results to a directory for
processing by the Junitreport Ant task.</td>
</tr>
</tbody>
</table>
<h2><a name="PDETestExampleProjects.zip_Contents"></a>PDETestExampleProjects-3.3.zip
Contents</h2>
<p>The ZIP file contains 3 separate plug-ins (each with their own Ant
build.xml file) and an overall Ant build.xml file that coordinates the
build and test of the 3 plug-ins.</p>
<table cellpadding="2" cellspacing="2">
<tbody>
<tr>
<th>Contents</th>
<th>Type</th>
<th>Description</th>
</tr>
<tr>
<td>pde.test.utils</td>
<td>Plug-in</td>
<td>Provides the PDE test utilities used by Ant to run the PDE
unit tests, including the following classes:<br>
<ul>
<li>pde.test.utils.PDETestListener</li>
<li>pde.test.utils.PDETestPortLocator</li>
<li>pde.test.utils.PDETestResultsCollector</li>
</ul>
</td>
</tr>
<tr>
<td>PhoneBookExample</td>
<td>Plug-in</td>
<td>This is the main Eclipse plug-in PhoneBook example
application, including the following classes:<br>
<ul>
<li>phonebookexample.PhoneBookExamplePlugin</li>
<li>phonebookexample.actions.PhoneBookAction</li>
<li>phonebookexample.data.PhoneBook</li>
<li>phonebookexample.data.PhoneBookEntry</li>
<li>phonebookexample.dialogs.PhoneBookEditorDialog</li>
<li>phonebookexample.dialogs.PhoneBookEntryEditorDialog</li>
</ul>
<br>
For further details on the example application see <a
href="#Simple_Phonebook_Application">Appendix A</a> below.</td>
</tr>
<tr>
<td>PhoneBookExample-test</td>
<td>Plug-in Fragment</td>
<td>This is the Eclipse plug-in fragment for the PhoneBook plug-in
that contains the PDE unit tests for the PhoneBook GUI, including the
following test classes:<br>
<ul>
<li>phonebookexample.dialogs.PhoneBookEntryEditorDialogTest</li>
</ul>
<br>
For further details on PDE Unit tests for the example application see
<a href="#Example_PDE_Unit_Tests">Appendix B</a> below.</td>
</tr>
<tr>
<td>build.xml</td>
<td>Ant build file</td>
<td>Overall Ant build file, that provides targets that
coordinates the building and testing of the 3 plug-ins</td>
</tr>
<tr>
<td>readme.txt</td>
<td>Readme file</td>
<td>Provide basic information on how to run the example</td>
</tr>
<tr>
<td>project.properties</td>
<td>properties file</td>
<td>Specifies the target Eclipse and pde.test.utils versions
used in this project.</td>
</tr>
</tbody>
</table>
<h2><a name="PDE_Test_Utilities"></a>PDE Test Utilities
(pde.test.utils)</h2>
<p>This plug-in contains a set of utilities that help automate the
running and monitoring of PDE Unit tests. </p>
<h3><a name="PDETestPortLocator"></a>PDETestPortLocator</h3>
<p>This class is responsible for discovering the next available port
on a system, creating a properties file called <i>pde_test_port.properties</i>
and writing a property called <i>pde.test.port</i> into the file and
setting it to the value of the next available port. This port is then
used by the Eclipse test runner process when publishing the progress and
results of tests and the PDE test listener process listens on the port
and processes the test results. </p>
<h3><a name="PDETestListener"></a>PDETestListener</h3>
<p>This class is responsible for listening on a specified port as an
Eclipse test listener and outputting the results of the test
run in the same XML format that is output by the Ant <a
target="_blank"
href="http://ant.apache.org/manual/OptionalTasks/junit.html">junit</a>
task. The test result XML files can then be
converted into an easily interpreted HTML JUnit report by the Ant <a
target="_blank"
href="http://ant.apache.org/manual/OptionalTasks/junitreport.html">junitreport</a>
task.</p>
<h3><a name="PDETestResultsCollector"></a>PDETestResultsCollector</h3>
<p>This class is responsible for starting the PDETestListener on the
specified port, for a PDE test run. The PDETestResultsCollector
process takes 2 parameters as follows: </p>
<ol>
<li>PDE Test suite name - this is just a string that identifies
the PDE test suite name - usually the plug-in fragment name, e.g.
PhoneBookExample-test in our example code.</li>
<li>port number - specifies the port that the PDE test
runner process uses to publish PDE test progress and results, the PDE
test listener process listens on the port to process the test results.</li>
</ol>
<h2>Conclusion</h2>
<p>As stated in the introduction, there are several options available
for automating PDE tests; some more complex than others. The technique
detailed in this article provides another choice for build system
engineers. It delivers the following benefits:
</p>
<ol>
<li>Allows you to run your PDE Tests from the command line</li>
<li>Allows you to collect the PDE Tests results in a format that
can be easily interpreted (i.e. Junitreport format)</li>
<li>Allows you to integrate PDE Tests into any Ant-based build
system</li>
</ol>
<h2><a name="Simple_Phonebook_Application"></a>Appendix A: Example
Application - Simple Phonebook Application (PhoneBookExample)</h2>
<p>The example application is a simple PhoneBook
application and some simple GUI PDE Tests. The aim of this article is
to show how you can integrate your PDE unit tests into an Ant build. In
consideration of this, the
example application and it's PDE unit tests have been deliberately kept
as simple as possible. </p>
<p>The PhoneBook application is simple tool to store names and their
associated phone numbers. The application adds a simple "Phone" menu
item to the main menu as follows:</p>
<p><img src="images/phonebook_menu.gif"
style="width: 718px; height: 350px;" alt="Image of phonebook menu item">
</p>
<p>Clicking on "Edit Phone Book" menu item causes the Edit PhoneBook
Dialog to be displayed:</p>
<p><img src="images/phonebook_editor.gif"
style="width: 524px; height: 309px;"
alt="Image of PhoneBook editor dialog"></p>
<p>Clicking on "New" button causes the Edit PhoneBook Entry Dialog
to be displayed:</p>
<p><img src="images/phonebook_entry_editor.gif"
style="width: 523px; height: 298px;"
alt="Image of PhoneBook Entry Editor dialog"></p>
<h3><a name="Making_GUI_Classes_testable_using"></a>Making GUI
Classes testable using package protection</h3>
<p><img src="images/tip.gif" alt=""> Throughout the simple GUI
examples provided here, a deliberate style of making all
fields in GUI classes <em>package protected</em> has been followed. Making the
fields package protected allows the unit tests to access the GUI
components during a test run.</p>
<p>For example, the local variables <img src="images/tag_1.gif"
align="middle" height="13" width="24"> are all package protected.</p>
<pre>package phonebookexample.dialogs;<br>...<br>public class PhoneBookEntryEditorDialog extends TitleAreaDialog {
<img src="images/tag_1.gif" align="middle" height="13" width="24"> PhoneBookEntry phoneBookEntry;
<img src="images/tag_1.gif" align="middle" height="13" width="24"> Composite phoneBookEntryComposite;
<img src="images/tag_1.gif" align="middle" height="13" width="24"> Text nameText;
<img src="images/tag_1.gif" align="middle" height="13" width="24"> Text numberText;
...
}</pre>
<p>Note that this is not an ideal solution for making your GUI
classes testable, but it is simple and it works.</p>
<h2><a name="Example_PDE_Unit_Tests"></a>Appendix B: Example PDE
Unit Tests (PhoneBookExample-test)</h2>
<p>There is just a single PDE JUnit test class provided in the example
(PhoneBookEntryEditorDialogTest) and most of the tests there are pretty
straightforward, but there are a few tricks or techniques that do
require some further explanation. </p>
<h3>Accessing the active shell</h3>
<p><img src="images/tip.gif" alt=""> The active shell for your
GUI under test can be accessed using the following:</p>
<pre> PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell()</pre>
<h3>Extending the GUI class under test to access protected methods</h3>
<p><img src="images/tip.gif" alt=""> This is a simple
technique to allow your test to gain access to protected methods in the
class under test or one of it's super classes. In the example the local
class MyPhoneBookEntryEditorDialog extends the class under test
PhoneBookEntryEditorDialog so that the tests can access the,
getButton(int id), buttonPressed() and cancellPressed() methods these
methods can then be used in the tests.</p>
<pre>class MyPhoneBookEntryEditorDialog extends PhoneBookEntryEditorDialog {
public MyPhoneBookEntryEditorDialog(Shell parent, PhoneBookEntry phoneBookEntry) {
super(parent, phoneBookEntry);
}
@Override
protected void buttonPressed(int buttonId) {
super.buttonPressed(buttonId);
}
@Override
protected void cancelPressed() {
super.cancelPressed();
}
@Override
protected Button getButton(int id) {
return super.getButton(id);
}
}</pre>
<h3>Making GUI Classes testable using package protection</h3>
<p>Making the local variables package protected allows the unit
tests to access the GUI components during the rest run (see the <a
href="article.html#Making_GUI_Classes_testable_using">earlier
section</a> for further details).</p>
<h2>Acknowledgements</h2>
<p>This technique for automating PDE unit tests was first developed
by David Bosschaert at IONA Technologies.</p>
<p>I'd like to thank Edwin Dankert and Sean Boylan, both of Duolog
Technologies who helped refine the technique and the article.
I'd also like to thank the reviewers Edwin Dankert, David
Bosschaert, Andrew Niefer of IBM and Wayne Beaton of Eclipse
for taking the time to read the article and provide all the excellent
feedback.</p>
</div>
<div class="notices">
<h3>Legal Notices</h3>
<p>Java and all Java-based trademarks and logos are trademarks or
registered trademarks of Sun Microsystems, Inc. in the United States,
other countries, or both.</p>
</div>
</body>
</html>