| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> | |
| <html> | |
| <head> | |
| <meta name="generator" content="HTML Tidy, see www.w3.org"> | |
| <meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> | |
| <title>Build and Test Automation for plug-ins and features</title> | |
| <link type="text/css" rel="stylesheet" href="../default_style.css"> | |
| <link type="text/css" rel="stylesheet" href="automation_style.css"> | |
| </head> | |
| <body link="#0000ff" vlink="#800080"> | |
| <div align="right"> | |
| <font face="Times New Roman, Times, serif" size="2">Copyright | |
| © 2005 Markus Barchfeld</font> | |
| <table border="0" cellpadding="2" cellspacing="0" width="100%"> | |
| <tbody> | |
| <tr> | |
| <td colspan="2" align="left" bgcolor="#0080c0" valign="top"> | |
| <b><font face="Arial,Helvetica"><font color="#ffffff"> Eclipse | |
| Corner Article</font></font></b></td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| </div> | |
| <div align="left"> | |
| <h1><img src="../images/Idea.jpg" align="middle" height="86" width= | |
| "120"></h1> | |
| </div> | |
| <p> </p> | |
| <h1 align="center">Build and Test Automation for plug-ins and features</h1> | |
| <blockquote> | |
| <p><b>Summary</b><br> | |
| Eclipse offers the possibility to build plug-ins automatically outside | |
| the Eclipse IDE, which is called "headless build". Eclipse itself is | |
| built headless and since Eclipse is an assembly of plug-ins, this feature | |
| is also available for any other plug-in. Although the set up of automatic | |
| building and testing requires only a couple of files, it can be tedious | |
| work to do nonetheless. This article shares the experiences and lessons | |
| learned while setting up automatic building and testing for an | |
| Open-Source Eclipse plug-in called RDT, Ruby Development Tools.</p> | |
| <p><b>By Markus Barchfeld, Zuehlke Engineering</b><br> | |
| <font size="-1">May 29, 2005</font></p> | |
| </blockquote> | |
| <hr width="100%"> | |
| <h3>Environment</h3> | |
| <p>All the techniques, examples and screen shots covered in this article | |
| refer to Eclipse 3.0. If you want to follow the examples, you will need an | |
| Eclipse 3.0.x installation. They might work with Eclipse 3.1 as well, but | |
| it is untested.</p> | |
| <p>The first part of this article gives an overview of the building steps | |
| and artifacts of the headless build and introduces the required files to | |
| build RDT as example. The second part shows how the Eclipse Test Framework | |
| can be leveraged to extend the automatic build by running a suite of test | |
| cases on the built plug-ins.</p> | |
| <h2>Part 1 - Automated Build</h2> | |
| <h3>Build a feature using PDE GUI Tools</h3> | |
| <p>Starting the development of a plug-in is quite easy with the PDE | |
| environment. There are tutorials and examples available which create sample | |
| plug-in projects in the workspace. Compilation is done automatically from | |
| the IDE and running the project can be easily achieved with starting a | |
| runtime workbench, thanks to the self hosting feature of Eclipse.</p> | |
| <p>For deployment you need to create a zip file which contains at least the | |
| plugin.xml and a jar file with the classes of the plug-in. The inclusion of | |
| further files (e.g. html files, images) can be controlled with the | |
| build.properties file, the PDE (Plug-in Development Environment) provides | |
| the "Build Properties Editor" for convenient editing of the file. <a href= | |
| "#pdeHelpBuildProperties">[1]</a> explains the content of build.properties. | |
| Fig. 1 shows the menu entry for the creation of an Ant build file. The | |
| build file will be called build.xml and be located in the same directory as | |
| the plugin.xml. The build file creation can be controlled with | |
| build.properties. Some of the properties are described in <a href= | |
| "#pdeHelpGenAnt">[2]</a>, see also Fig. 5. If you have the need to | |
| customize the build process beyond the possibilities of build.properties, a | |
| custom build file can be provided. Of course, the custom build file must | |
| provide the same "interface" as the generated build file has, i.e. there | |
| are some mandatory targets, which are explained in <a href= | |
| "#usingPDEBuild">[12]</a>.</p> | |
| <div class="figure"> | |
| <img style="width: 441px; height: 113px;" alt="Create Ant Build File" | |
| src="createAntBuildFile.png"> | |
| <div class="figure-caption"> | |
| <span class="figure-number">Fig 1</span>. Create Ant Build file<br> | |
| </div> | |
| </div> | |
| <br> | |
| <br> | |
| <p>The simplest method of deployment is to choose a zip file as the | |
| deliverable and then to unzip the build output into the plugins directory | |
| of your target Eclipse installation. More sophisticated deployment options | |
| are update sites and product extensions. If the project grows then you may | |
| to split it up into several plug-in projects, at least plug-in projects | |
| which contain GUI components and Core plug-in projects which do not contain | |
| GUI components. They can still be built and deployed separately, but having | |
| an Eclipse feature provides additional advantages and so you probably want | |
| to wrap up the plug-ins with a feature project.</p> | |
| <p>Fig. 2 shows the Feature Manifest Editor. The Export... button opens the | |
| Feature Export Dialog (Fig. 3) with which you can create the deliverable: | |
| either a single zip file or the file structure for an update site. Behind | |
| the scenes the feature build process just builds every contained plug-in as | |
| described above and then collects the results. All the generated build | |
| files are temporary and will be deleted after the build has finished. The | |
| build file generation for every contained plug-in works in exactly the same | |
| way as if called from the "Create Ant Build File" menu entry, which also | |
| means that the build.properties file of every plug-in is considered in the | |
| same way as if the plug-in would be built standalone.</p> | |
| <p>Additionally there is a build.xml file created for the feature project. | |
| Like the plug-ins build file, the build.xml for the feature can be created | |
| with the PDE Tools->Create Ant Build File context menu on the | |
| feature.xml file. Similar to the plug-ins, there is a build.properties file | |
| for the feature which can be used to customize the build process. E.g: the | |
| files you choose to include into a binary build are defined in the | |
| bin.includes property in build.properties. Some of the properties of | |
| build.properties can be conveniently set with the Feature Manifest Editor. | |
| E.g the bin.includes property can be assembled on the "Build" tab with a | |
| tree control and check boxes.</p> | |
| <p>Although the Feature Export Dialog allows storing the build-action in a | |
| single build script, it is not yet the solution for a fully automated build | |
| process, because this script can not be run outside of an Eclipse | |
| workbench. Its purpose is to save the settings chosen in the Feature Export | |
| Dialog and conveniently rerun the same export function again by choosing | |
| Run->Ant Build (<a href="#bugsHeadlessInvokation">[3]</a>). For building | |
| outside of Eclipse, PDE provides some Ant tasks which are explained in <a | |
| href="#pdeHelpGenCommandLine">[4]</a>. But In order to use them you don't | |
| have to create Ant scripts from scratch. There is already an infrastructure | |
| for headless builds, which can be leveraged.</p> | |
| <div class="figure"> | |
| <img src="featureManifestEditor.png" height="421" width="518"> | |
| <div class="figure-caption"> | |
| <span class="figure-number">Fig 2</span>. Feature Manifest Editor | |
| </div> | |
| </div> | |
| <p> </p> | |
| <div class="figure"> | |
| <img src="exportFeaturesDialog.png" height="487" width="378"> | |
| <div class="figure-caption"> | |
| <span class="figure-number">Fig 3</span>. Export Features Dialog | |
| </div> | |
| </div> | |
| <h3>Build headless</h3> | |
| <p>There are many reasons for creating a batch build process such as | |
| providing a nightly or continuous build. This requires a fully automatic | |
| build which can even start with the retrieval of the sources from CVS. | |
| Eclipse itself is built in that way and because "everything is a plug-in" | |
| the mechanisms can also be applied for the build of arbitrary plug-ins. | |
| However it is necessary to bundle your plug-ins into a feature project if | |
| you want to use headless build. If there is no real need to deploy your | |
| plug-in(s) using a feature, a feature project can also be used for the | |
| build process only. In this case there will be no feature manifest added to | |
| the deliverable.</p> | |
| <p>The infrastructure is provided by the PDE and the RelEng (Release | |
| Engineering) plug-ins. The org.eclipse.releng.basebuilder plug-in contains | |
| a complete Eclipse installation for the build, but any Eclipse-SDK is | |
| sufficient. The org.eclipse.releng.eclipsebuilder plug-in contains control | |
| files for the build of parts like JDT, PDE, and all the other plug-ins | |
| which are part of the Eclipse distribution.</p> | |
| <p>Although the build.xml provided in org.eclipse.releng.eclipsebuilder | |
| looks like a plain Ant build file, there are Ant-Tasks required which are | |
| provided from the PDE. Therefore the script must be executed in an Eclipse | |
| environment. Because it would not be suitable for batch processing to start | |
| up the Eclipse workbench, there is a "headless" startup mode provided, | |
| which means that Eclipse is started without loading GUI plug-ins. To start | |
| up a headless Eclipse instance which then executes an Ant build file, | |
| Eclipse must be started as AntRunner application. An example is given in | |
| Fig. 10.</p> | |
| <h4>Building sdk.examples headless</h4> | |
| <p>As an example, let's build one of the Eclipse deliverables headless. The | |
| feature sdk.examples is chosen, because it is quite small, the deliverable | |
| is about 1.8 Mb (<a href="#eclipsExamples">[5])</a>. The headless build | |
| takes about 10 minutes on my 1.6Ghz Win XP laptop, most of the time used | |
| for fetching the sources via a 64k internet connection. In addition to an | |
| Eclipse installation there are two prerequisites for the headless | |
| build:</p> | |
| <ul> | |
| <li><a target="extra" href="http://www.cvshome.org/">CVS</a> client | |
| version 1.10 or higher on system path.</li> | |
| <li><a target="extra" href= | |
| "http://www.info-zip.org/pub/infozip/">Info-Zip</a> zip and unzip | |
| executables on system path.</li> | |
| </ul> | |
| <p>The first step is to get org.eclipse.releng.eclipsebuilder:</p> | |
| <pre> | |
| D:\build>cvs -d :pserver:anonymous@dev.eclipse.org:/cvsroot/eclipse export -r R3_0_2 org.eclipse.releng.eclipsebuilder | |
| </pre> | |
| <p>The readme.html in org.eclipse.releng.eclipsebuilder (<a href= | |
| "#eclipsebuilderReadme">[6])</a> describes how to build a component. By | |
| default, components are built with an Eclipse instance (build host) defined | |
| in org.eclipse.releng.basebuilder. But because the basebuilder is rather | |
| large, we can also use an existing Eclipse-3.0.2 installation as build | |
| host. Because it is not assured that the Eclipse-3.0.2 host can compile the | |
| current Eclipse components, we use the 3.0.2 version of eclipsebuilder in | |
| this example. In order to fetch the 3.0.2 version of sdk.examples instead | |
| of the HEAD version, we have to modify | |
| org.eclipse.releng.eclipsebuilder/sdk.examples/build.properties and set the | |
| property mapVersionTag appropriately:</p> | |
| <pre> | |
| mapVersionTag=R3_0_2 | |
| </pre> | |
| <p>Now the build can be started from the command line:</p> | |
| <pre> | |
| D:\build\org.eclipse.releng.eclipsebuilder>set ECLIPSE_HOME=D:\eclipse\eclipse-3.0.2 | |
| D:\build\org.eclipse.releng.eclipsebuilder>java -cp %ECLIPSE_HOME%\startup.jar org.eclipse.core.launcher.Main | |
| -application org.eclipse.ant.core.antRunner -buildfile build.xml | |
| -Dcomponent=sdk.examples -Dconfigs="*,*,*" -Dbaseos=win32 -Dbasews=win32 -Dbasearch=x86 -Djavacfailonerror=true | |
| -Dpde.build.scripts=%ECLIPSE_HOME%/plugins/org.eclipse.pde.build_3.0.1/scripts -DbaseLocation=%ECLIPSE_HOME% | |
| </pre> | |
| <p>The property "component" is used to define that the files in the | |
| sdk.examples subdirectory are used in the headless build, which are | |
| build.properties and customTargets.xml. The build takes place in | |
| D:\build\org.eclipse.releng.eclipsebuilder\src by default. This can be | |
| changed with the property buildDirectory. Either by adding | |
| -DbuildDirectory=${basedir}/newDirectory to the command above or by | |
| changing buildDirectory in | |
| org.eclipse.releng.eclipsebuilder/sdk.examples/build.properties.</p> | |
| <p>After the build has finished, the deliverable and compile logs can be | |
| found in the build output directory, a subdirectory of the build directory. | |
| The name of the output directory is defined by the buildLabel property. By | |
| default it starts with "I-" and includes the time stamp of the build | |
| time.</p> | |
| <p>The baseLocation is used during the build to provide missing plug-ins, | |
| i.e., plug-ins which are not part of the deliverable to build and have | |
| therefore not been fetched from CVS. After the plug-ins have been fetched, | |
| PDE reads in the plug-ins and creates a build time Eclipse host. If | |
| baseLocation is given, the Eclipse installation at baseLocation is added to | |
| the build time Eclipse host. In our case this is necessary, because | |
| sdk.examples depends on the plug-ins in the Eclipse SDK and can therefore | |
| not be built standalone. Note that the baseLocation is independent of the | |
| build host and therefore the build host can be another version of Eclipse. | |
| In the example we could use Eclipse 3.0.2 as build host and Eclipse 3.0 as | |
| baseLocation. The baseLocation may not contain any of the plug-ins to be | |
| built. If the baseLocation contained the sdk.examples, an error would | |
| occur.</p> | |
| <p>The next section looks behind the scenes of the headless build.</p> | |
| <h3>Build Phases</h3> | |
| <p>Fig. 4 shows the files which drive the build process. While build.xml | |
| and genericTargets.xml are provided from the PDE feature, there are two | |
| files to be provided by the plugin to be built: the customTargets.xml and | |
| build.properties. Examples for these two files can be found in | |
| org.eclipse.releng.eclipsebuilder\sdk.examples, if you did not download | |
| org.eclipse.releng.eclipsebuilder in the last section, see <a href= | |
| "#eclipsebuilderReadme">[7]</a>. The build.properties file allows | |
| customizing various build parameters, for a reference see Fig. 5. Fig. 6 | |
| shows the interaction of three build files, build.xml, genericTargets.xml | |
| and customTargets.xml, which accomplishes the build. The main phases of the | |
| build process are declared in build.xml: PreBuild, Fetch, Generate, | |
| Process, Assemble and PostBuild.</p> | |
| <div class="figure"> | |
| <table class="contentTable" cellspacing="2"> | |
| <tbody> | |
| <tr> | |
| <th>File name</th> | |
| <th>Location</th> | |
| <th>Description</th> | |
| </tr> | |
| <tr> | |
| <td><b>build.xml</b></td> | |
| <td>org.eclipse.pde.build_<version>/scripts</td> | |
| <td>This is the main build script and provides a skeleton for the | |
| build process: from prebuild to postbuild targets</td> | |
| </tr> | |
| <tr> | |
| <td><b>genericTargets.xml</b></td> | |
| <td>org.eclipse.pde.build_<version>/scripts</td> | |
| <td>Contains targets like fetchElement, generateScript, | |
| processElement, assembleElement</td> | |
| </tr> | |
| <tr> | |
| <td><b>customTargets.xml</b></td> | |
| <td>value of property <i>builder</i></td> | |
| <td>This build script resides in the location specified by the | |
| property <i>builder</i>. It is included from the main build.xml | |
| file and delegates to targets in genericTargets. The main | |
| responsibilities are in defining the features to build and to fetch | |
| the map files.</td> | |
| </tr> | |
| <tr> | |
| <td><b>build.properties</b></td> | |
| <td>value of property <i>builder</i></td> | |
| <td>This build script resides in the location specified by the | |
| property <i>builder</i>. It contains properties for fetching the | |
| sources, building and compiling.</td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| <div class="figure-caption"> | |
| <span class="figure-number">Fig 4</span>. Files for controlling the | |
| build process | |
| </div> | |
| </div> | |
| <br> | |
| <br> | |
| <div class="figure"> | |
| <table class="contentTable" cellspacing="2"> | |
| <tbody> | |
| <tr> | |
| <th>Category</th> | |
| <th>Name</th> | |
| <th>Description</th> | |
| </tr> | |
| <tr> | |
| <td rowspan="3">Build folder</td> | |
| <td>buildDirectory</td> | |
| <td>The relative path to a directory where the source for the build | |
| will be exported, where scripts will be generated and where the end | |
| products of the build will be located. On Windows systems, this | |
| directory should be close to the drive root to avoid path length | |
| limitations particularly at compile time.</td> | |
| </tr> | |
| <tr> | |
| <td>baseLocation</td> | |
| <td>A directory separate from ${buildDirectory} which contains | |
| pre-built plug-ins against which to compile. ${baseLocation} must | |
| not contain any features, plug-ins or fragments which are already | |
| or will be located in ${buildDirectory}.</td> | |
| </tr> | |
| <tr> | |
| <td>baseos,basews,basearch,basenl</td> | |
| <td>The os, ws, arch and nl values of the pre-built Eclipse found | |
| in ${baseLocation}.</td> | |
| </tr> | |
| <tr> | |
| <td rowspan="7">Build target (what is being built)</td> | |
| <td>configs</td> | |
| <td>An ampersand separated list of configurations to build for an | |
| element where a configuration is specified as | |
| <os>,<ws>,<arch>.<br> | |
| ie.configs="win32,win32,x86 & linux, motif, x86 & linux, | |
| gtk, x86". Typically used to build a feature that is os, ws, arch | |
| specific. A non-platform specific configuration is specified with | |
| "*,*,*".</td> | |
| </tr> | |
| <tr> | |
| <td>collectingFolder</td> | |
| <td>The directory in which built features and plug-ins are | |
| gathered. This is typically set to "eclipse".</td> | |
| </tr> | |
| <tr> | |
| <td>archivePrefix</td> | |
| <td>The top level directory in assembled distribution. This is | |
| typically set to "eclipse".</td> | |
| </tr> | |
| <tr> | |
| <td>buildType</td> | |
| <td>A letter "I, N, S, R or M" used to identify builds as being one | |
| of the following:<br> | |
| <br> | |
| I - Integration<br> | |
| N - Nightly<br> | |
| S - Stable<br> | |
| R - Release<br> | |
| M - Maintenance<br> | |
| </td> | |
| </tr> | |
| <tr> | |
| <td>buildId</td> | |
| <td>The build name. Default set to "build" in template | |
| build.properties.</td> | |
| </tr> | |
| <tr> | |
| <td>buildLabel</td> | |
| <td>Refers to the name of the directory which will contain the end | |
| result of the build. Set to ${buildType}.${buildId} in template | |
| build.properties. This directory will be created in the | |
| ${buildDirectory}.</td> | |
| </tr> | |
| <tr> | |
| <td>timestamp</td> | |
| <td>A timestamp used to fill in value for buildid in about.mappings | |
| files. Also used to name build output directory, i.e. | |
| I-build-<timestamp>.</td> | |
| </tr> | |
| <tr> | |
| <td rowspan="2">Repository</td> | |
| <td>mapVersionTag</td> | |
| <td>Sets the tag attribute in a call to the <a target="extra" href= | |
| "http://ant.apache.org/manual/CoreTasks/cvs.html">Ant <cvs> | |
| task</a> to check out the map file project.</td> | |
| </tr> | |
| <tr> | |
| <td>fetchTag</td> | |
| <td>Sets the tag or branch when exporting modules used in the | |
| build. For example, setting fetchTag=HEAD will fetch the HEAD | |
| stream of the source for all features, plug-ins and fragments | |
| listed in the map files instead of fetching the tag specified in | |
| the map entry for that element. For example this is being used in | |
| the eclipse build process to produce the nightly build.</td> | |
| </tr> | |
| <tr> | |
| <td rowspan="6">Java Compiler</td> | |
| <td>bootclasspath</td> | |
| <td>Sets the value for the attribute "bootclasspath" in calls to | |
| the <a target="extra" href= | |
| "http://ant.apache.org/manual/CoreTasks/javac.html">Ant | |
| <javac> task</a> in a plug-in's build.xml.</td> | |
| </tr> | |
| <tr> | |
| <td>javacDebugInfo</td> | |
| <td>Sets the value for the attribute "debug" in calls to the <a | |
| target="extra" href= | |
| "http://ant.apache.org/manual/CoreTasks/javac.html">Ant | |
| <javac> task</a> in a plug-in's build.xml. Determines if | |
| debug info is included in the output jars. Set to on in template | |
| build.properties.</td> | |
| </tr> | |
| <tr> | |
| <td>javacFailOnError</td> | |
| <td>Sets the value for the attribute "failonerror" in calls to the | |
| <a target="extra" href= | |
| "http://ant.apache.org/manual/CoreTasks/javac.html">Ant | |
| <javac> task</a> in a plug-in's build.xml. Build will | |
| continue even if there are compilation errors when this is set to | |
| false.</td> | |
| </tr> | |
| <tr> | |
| <td>javacSource</td> | |
| <td>Sets the value for the attribute "source" in calls to the <a | |
| target="extra" href= | |
| "http://ant.apache.org/manual/CoreTasks/javac.html">Ant | |
| <javac> task</a> in a plug-in's build.xml. Sets the value of | |
| the -source command line switch for javac version 1.4. Used when | |
| compiling the jars for the plug-ins. Default set to 1.3 in | |
| generated build.xml for plug-ins and fragments.</td> | |
| </tr> | |
| <tr> | |
| <td>javacTarget</td> | |
| <td>Sets the value for the attribute "target" in calls to the <a | |
| target="extra" href= | |
| "http://ant.apache.org/manual/CoreTasks/javac.html">Ant | |
| <javac> task</a> in a plug-in's build.xml. Sets the value of | |
| the -target command line switch for javac. Used when compiling the | |
| jars for the plug-ins. Default set to 1.1 in generated build.xml | |
| for plug-ins and fragments.</td> | |
| </tr> | |
| <tr> | |
| <td>javacVerbose</td> | |
| <td>Sets the value for the attribute "verbose" in calls to the <a | |
| target="extra" href= | |
| "http://ant.apache.org/manual/CoreTasks/javac.html">Ant | |
| <javac> task</a> in a plug-in's build.xml. Asks the compiler | |
| for verbose output. Default set to true.</td> | |
| </tr> | |
| <tr> | |
| <td>misc</td> | |
| <td>zipargs</td> | |
| <td>Arguments to send to the zip executable. Setting it to -y on | |
| Linux preserves symbolic links.</td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| <div class="figure-caption"> | |
| <span class="figure-number">Fig 5</span>. build.properties | |
| </div> | |
| </div> | |
| <br> | |
| <br> | |
| <div class="figure"> | |
| <img src="buildInteractionDiagram.png"> | |
| <div class="figure-caption"> | |
| <span class="figure-number">Fig 6</span>. Script interaction for the | |
| build process<br> | |
| </div> | |
| </div> | |
| <h4>PreBuild and Fetch phase</h4> | |
| <p>Fig. 7 gives an overview of the main activities and the files created | |
| from these activities for the complete build process. The getMapFiles and | |
| concatenate activities are part of the PreBuild phase; fetch and getFromCVS | |
| are part of the Fetch phase.</p> | |
| <p>The most important task in the PreBuild phase is to retrieve map files, | |
| which is implemented in the getMapFiles target in customTargets.xml. | |
| Usually the getMapFiles target consists of a CVS command to fetch the map | |
| files. A map file is a java property file which contains mappings of | |
| elements to their CVS locations and access methods. It consists of one map | |
| file entry for each feature being built, its <plugin> elements, and | |
| its <includes> elements (i.e. nested features and their plug-ins). | |
| Adding a plug-in or fragment to a feature therefore requires updating the | |
| map files with the new element.</p> | |
| <p>Map file entries use the following format:</p> | |
| <pre> | |
| feature|fragment|plugin@elementId=<cvs tag>,<access method>:<cvsuser>@<cvs repository>,<cvs password>[,<repository path> (no starting slash) ] | |
| </pre> | |
| <p>The <repository path> is only required when the module (or | |
| directory) containing the source for the element does not match the | |
| elementId or if the directory is not at the root of the repository. Because | |
| all the map files are concatenated into a single file called Directory.txt | |
| after getMapFiles has finished, the format of directory.txt described in <a | |
| href="#pdeHelpGenCommandLine">[4]</a> applies also to the format of a map | |
| file.</p> | |
| <p>The fetch phase starts with the creation of an ant script called | |
| retrieve.xml, which contains a build target for fetching the feature.xml. | |
| Then this target will be executed and the information about the provided | |
| plug-ins of the feature is read in. For every provided plug-in a | |
| corresponding build target will be added to the fetch build script. Both | |
| files (retrieve.xml and feature.xml) are only temporary. They will be | |
| deleted after the fetch build script has been generated.</p> | |
| <p>The fetch build script is named fetch_<element_id>.xml, where | |
| <element_id> is substituted with the feature id read from the | |
| feature.xml file (not the property "id" given in customTargets.xml). | |
| Running the default target "fetch" of this build script calls the target | |
| getFromCVS for the feature itself and all included plug-ins. The sources of | |
| the plugins are not fetched again in the case of an existing plugin.xml. | |
| So, if you run the full build twice in the same directory, the sources for | |
| the plug-ins are not fetched twice. But you need to have a working CVS | |
| connection nonetheless, because the retrieve.xml file is created and | |
| executed in any case. Therefore you would end up with an incomplete | |
| fetch_<element_id>.xml file if you run the fetch phase and did not | |
| have CVS connection.</p> | |
| <br> | |
| <br> | |
| <div class="figure"> | |
| <img src="fetchProcessActivity.png" height="780" width="464"> | |
| <div class="figure-caption"> | |
| <span class="figure-number">Fig 7</span>. File flow of the build | |
| process | |
| </div> | |
| </div> | |
| <h4>Generate Phase</h4> | |
| <p>After the feature and plug-ins have been copied to the build target | |
| directory, the build scripts are generated in the same way as they would be | |
| with the PDE GUI (see above). The created files are:</p> | |
| <ul> | |
| <li>a build file in every plug-in directory (unless custom build files | |
| are used)</li> | |
| <li>a build file in the feature directory</li> | |
| <li>assemble_<element_id>.all.xml and | |
| assemble_<element_id>.all.xml</li> | |
| </ul> | |
| <h4>Process and Assemble Phase</h4> | |
| <p>At this point of the build process the build files are in place and the | |
| compilation is started from a call to processElement in genericTargets.xml. | |
| This in turn calls the target build.jars in the build.xml file in the | |
| feature directory. There the compilation starts and the warning and error | |
| messages of the java compiler are collected separately for each jar file. | |
| The files are named <jarFileName>.bin.log and reside in a | |
| subdirectory "temp.folder". Later these files are gathered and copied to | |
| the build output directory.</p> | |
| <p>The assembly is started from the assembleElement target in | |
| genericTargets.xml which then calls a target named assemble.${id} in | |
| customTargets.xml. This gives the chance to do some work before or after | |
| the assembly, but the main part of the work can just be delegated to the | |
| assemble.${id}.all.xml in the build target directory.</p> | |
| <p>The assemble script copies all the build results to a temporary | |
| subdirectory in the build target directory and finally zips them up. The | |
| files being collected are feature manifest files (feature.xml), plug-in | |
| manifest files (plugin.xml) and the built jar files. The inclusion of | |
| arbitrary files can be specified with the bin.includes property of the | |
| plug-in's build.properties file <a href= | |
| "#pdeHelpBuildProperties">([1]</a>).</p> | |
| <h4>PostBuild Phase</h4> | |
| <p>This is a build hook which is empty per default and allows performing | |
| actions with the build output. We will use this later for test | |
| automation.</p> | |
| <blockquote> | |
| <p><img src="../images/tip.gif" height="13" width="62"> After | |
| modifications to the build files you can save time if you run only a | |
| particular phase of the build process. E.g. if you changed a property | |
| which only affects the process phase, you can run this phase alone by | |
| appending process to the -buildfile argument in the command line:</p> | |
| <pre> | |
| java org.eclipse.core.launcher.Main -application org.eclipse.ant.core.antRunner -buildfile %buildfile% process | |
| </pre> | |
| </blockquote> | |
| <h3>How to build your Plug-In</h3> | |
| <p>Now we have built sdk.examples headless and have an overview of the | |
| build process. Build automation for your plug-in is not far away anymore | |
| with one constraint: you need to provide a feature project if you want to | |
| fully leverage the headless build as you have seen it for sdk.examples. So, | |
| if you don't have a feature project created yet, now is the time. With the | |
| IDE you can create a feature project with | |
| File->New->Project...->Plug-in Development->Feature Project. In | |
| the wizard which opens enter a feature name and then select all the | |
| plug-ins you want to include in your build. If you do not want to deploy | |
| your plug-in(s) as a feature, you can configure the feature project so that | |
| it is only be used to drive the build process but will not be included in | |
| the deliverable. Therefore just remove the bin.includes property from the | |
| build.properties file of the feature project.</p> | |
| <p>Using the feature there need to be 4 files defined in order to provide a | |
| one step build:</p> | |
| <ul> | |
| <li>a map file for fetching the sources</li> | |
| <li>customTargets.xml</li> | |
| <li>build.properties</li> | |
| <li>a shell script, which starts an Eclipse instance as AntRunner</li> | |
| </ul> | |
| <p>Fig. 8 shows a part of the map file for RDT. The CVS method used is ext, | |
| which allows to configure access parameters like user name, password or SSH | |
| proxy locally. In the case that pserver should be used, the getMapFiles | |
| target of customTargets.xml replaces ext with pserver.</p> | |
| <div class="figure" style="text-align: left;"> | |
| <pre> | |
| feature@org.rubypeople.rdt=HEAD,:ext:cvs.sf.net:/cvsroot/rubyeclipse,,org.rubypeople.rdt-feature | |
| plugin@org.kxml2=HEAD,:ext:cvs.sf.net:/cvsroot/rubyeclipse, | |
| plugin@org.rubypeople.rdt=HEAD,:ext:cvs.sf.net:/cvsroot/rubyeclipse, | |
| plugin@org.rubypeople.rdt.core=HEAD,:ext:cvs.sf.net:/cvsroot/rubyeclipse, | |
| </pre> | |
| <div class="figure-caption"> | |
| <span class="figure-number">Fig 8</span>. A section from rdt.map | |
| </div> | |
| </div> | |
| <p>As seen above customTargets.xml is the build file which provides hooks | |
| to customize the build process. A template for customTargets.xml can be | |
| found in <a href="#pdeScripts">[9]</a>. Fig. 9 shows the parts of the | |
| customTargets.xml file which have to be modified as a minimum for the build | |
| process:</p> | |
| <ol> | |
| <li>Define the Feature to be built in the allElements target. The given | |
| id is not the Feature id as defined in the feature manifest but only an | |
| identifier for the lookup in the map file.</li> | |
| <li>Retrieve map files in the getMapFiles target. Usually the map files | |
| are fetched from CVS and copied to the maps subdirectory of | |
| ${buildDirectory}.</li> | |
| <li>Provide a target called assemble.<id>. This can just delegate | |
| to the assemble script which has been created in the generate phase of | |
| the build process.</li> | |
| </ol> | |
| <div class="figure"> | |
| <div style="text-align: left;"> | |
| <pre> | |
| <target name="allElements"> | |
| <ant antfile="${genericTargets}" target="${target}" > | |
| <property name="type" value="feature" /> | |
| <property name="id" value="org.rubypeople.rdt" /> | |
| </ant> | |
| </target> | |
| <target name="getMapFiles"> | |
| <property name="cvsRoot" value=":ext:cvs.sf.net:/cvsroot/rubyeclipse" /> | |
| <cvs cvsroot="${cvsRoot}" | |
| dest="${buildDirectory}/maps" | |
| command="export -r ${mapVersionTag} org.rubypeople.rdt.build/map"/> | |
| </target> | |
| <target name="assemble.org.rubypeople.rdt"> | |
| <ant antfile="${assembleScriptName}" dir="${buildDirectory}"> | |
| <property name="zipargs" value="" /> | |
| </ant> | |
| </target> | |
| </pre> | |
| </div> | |
| <div class="figure-caption"> | |
| <span class="figure-number">Fig 9</span>. Mandatory changes in | |
| customTargets.xml | |
| </div> | |
| </div> | |
| <h4>Build RDT as example</h4> | |
| <p>All the files which configure the headless build for RDT can be found in | |
| <a href="#buildBootstrapFilesRdt">[10]</a>. In order to build RDT, you must | |
| have an Eclipse 3.0.x installation, CVS installed and CVS access to the | |
| internet (firewall!). The sources will be fetched from cvs.sf.net, which | |
| provides anonymous access.</p> | |
| <p>First we need to get the bootstrap for the headless build:</p> | |
| <pre> | |
| cvs -d :pserver:anonymous@cvs.sf.net:/cvsroot/rubyeclipse export -r R0_5_0 org.rubypeople.rdt.build/bootstrap | |
| </pre> | |
| <p>After a successful retrieval you will find the following files: README, | |
| run.bat, run.sh, customTargets.xml and build.properties. The map file | |
| defines to fetch the HEAD version of all plug-ins. In order to get stable | |
| sources, the property fetchTag is set in build.properties and overwrites | |
| the settings from the map file. See <a href="#pdeScripts">[9]</a> for a | |
| description of the build file options. Now change the variables in the run | |
| script (run.bat on windows or run.sh on UNIX) so that they reflect your PCs | |
| environment.</p> | |
| <ul> | |
| <li>Adapt eclipseDir and pdeBuildPluginVersion to the Eclipse | |
| installation you want to use for the build</li> | |
| <li>Set the buildDirectory </li> | |
| <li>The variable docbook.root can be commented out</li> | |
| <li>The variable pluginAutomaticBuildDir must be set to the absolute path | |
| of the bootstrap directory</li> | |
| <li>If java 1.4.x is not available on the classpath, vm must be set to | |
| the location of a java 1.4.x executable. </li> | |
| </ul> | |
| <p>Now the execution of the run script should build RDT. If it does not, | |
| test your skills in handling the lengthy Ant stack traces.</p> | |
| <blockquote> | |
| <p><img src="../images/tip.gif" height="13" width="62">The | |
| build.properties file which is provided as template in <a href= | |
| "#pdeScripts">[9]</a> builds a result zip file which contains paths with | |
| "eclipse" prefix, e.g. "eclipse/feature/...". This is inconvenient if the | |
| zip file should be extracted into a renamed Eclipse installation | |
| directory, e.g. eclipse-3.0.2. Therefore the archive path names should be | |
| relative to the eclipse installation directory, which can be achieved by | |
| setting the properties collectingFolder and archivePrefix to ".".</p> | |
| </blockquote> | |
| <h4>Debug the Build Process</h4> | |
| <p>If you reach a point where the error messages during the build are more | |
| confusing than helpful, you can debug the build run. A first measure to | |
| take is to set the AntRunner to verbose mode: add a "-verbose" behind the | |
| AntRunner argument in the java command line. This gives detailed | |
| information about which Ant targets are executed. It is particularly useful | |
| for debugging problems with accessing CVS. If that does not help, the build | |
| run itself can be debugged. Instead of starting the build host from a shell | |
| script (.sh or .bat) you can start the build host from the Eclipse IDE with | |
| a Run Configuration. The custom Ant Tasks which PDE provides reside in the | |
| org.eclipse.pde.build plug-in project and set breakpoints or catch | |
| exceptions. Here is a step-by-step guide on how to set up an AntRunner | |
| Run-time Workbench:</p> | |
| <ol> | |
| <li>Start Eclipse and switch to an empty workspace</li> | |
| <li>File>Import, External plug-ins and Fragments</li> | |
| <li>Select "Projects with source folders"</li> | |
| <li>Add all plug-ins with org.eclipse.pde.*</li> | |
| <li> | |
| Create a Run-time Workbench run configuration (Run->Run..., Run-time | |
| Workbench) | |
| <ol> | |
| <li>Choose "org.eclipse.ant.core.antRunner" as "Run an | |
| application"</li> | |
| <li> | |
| Add Program Arguments: | |
| <ol> | |
| <li>-Dbuilder=$builder, where $builder is the directory where | |
| your customTargets.xml is located</li> | |
| <li>-DbaseLocation=$baseLocation, where $baseLocation is the | |
| directory of your Eclipse installation (see above)</li> | |
| </ol> | |
| </li> | |
| </ol> | |
| </li> | |
| <li>Add a breakpoint, e.g. in the method "generate" in | |
| org.eclipse.pde.build/src-pdebuild/org.eclipse.pde.internal.build.FetchScriptGenerator</li> | |
| <li>Start the debug session</li> | |
| </ol> | |
| <div class="figure"> | |
| <img style="width: 794px; height: 605px;" alt= | |
| "Run Configuration for building sdk.examples" src= | |
| "buildRunConfiguration.png"><br> | |
| <div class="figure-caption"> | |
| <span class="figure-number">Fig 10</span>. Run configuration for | |
| building sdk.examples<br> | |
| </div> | |
| </div> | |
| <p>Fig. 10 shows the Run configuration dialog for building sdk.examples, | |
| which we have built from command line above. The full Program Arguments | |
| are:</p> | |
| <pre> | |
| -buildfile "D:\build\org.eclipse.releng.eclipsebuilder\build.xml" -Dcomponent=sdk.examples -Dconfigs="*,*,*" | |
| -Dbaseos=win32 -Dbasews=win32 -Dbasearch=x86 -Djavacfailonerror=true | |
| -Dpde.build.scripts=D:/eclipse/eclipse-3.0.2/plugins/org.eclipse.pde.build_3.0.1/scripts -DbaseLocation=D:\eclipse\eclipse-3.0.2 | |
| </pre> | |
| <p>Note the location of the build workspace. The log file in | |
| D:\build\build-workspace\.metadata\.log often provides useful information | |
| if a build fails.</p> | |
| <h4>Include sources</h4> | |
| <p>Unfortunately the headless build does not support all of the settings as | |
| they are provided by the Feature Export Dialog (Fig. 3). For example, the | |
| inclusion of source jar files is not possible. This lack can be | |
| circumvented by using a source feature or plug-in. Building a source | |
| feature is quite convenient and needs only two entries to be added:</p> | |
| <ol> | |
| <li> | |
| Add a Line to build.properties of your feature project: | |
| <pre> | |
| generate.feature@org.rubypeople.rdt.source=org.rubypeople.rdt | |
| </pre> | |
| </li> | |
| <li> | |
| Add an xml element to feature.xml: | |
| <pre> | |
| <includes id="org.rubypeople.rdt.source" version="0.0.0"/> | |
| </pre> | |
| If the version is set to 0.0.0, the version of the containing plug-in | |
| will be used. | |
| </li> | |
| </ol> | |
| <p>Further customization of the source feature generation can be achieved | |
| by creating the subdirectories "sourceTemplatePlugin" and | |
| "sourceTemplateFeature" in your feature project. These directories should | |
| contain the files that are included in the root of the generated source | |
| feature and plug-in. The feature.xml and plugin.xml files are not required | |
| since these are generated. A build.properties is required in the | |
| sourceTemplatePlugin directory. This should contain a "bin.includes" | |
| setting as well as the entry "sourcePlugin = true". The plugin.xml file and | |
| src/ directory should be listed in bin.includes.</p> | |
| <blockquote> | |
| <p><img src="../images/tip.gif" height="13" width="62"> If there is an | |
| includes tag in feature.xml, building with the Export... button from the | |
| Feature Manifest Editor fails (<a href= | |
| "#generateSourceFeatureBug">[16]</a>). As a workaround the feature.xml of | |
| the RDT project contains only an xml comment. The comment will be | |
| replaced with the includes tag in the postFetch target in | |
| customTargets.xml. The generate.feature property must be treated in a | |
| similar way.</p> | |
| </blockquote> | |
| <h4>Build for Update Site</h4> | |
| <p>If you want to build files for an update site customTargets.xml can be | |
| modified to call the build.update.jar target of the feature build file. The | |
| results can then be copied to the update site location. Fig. 11 shows the | |
| changes in customTargets.xml, following the idea in <a href= | |
| "#discussionUpdateSiteBuild">[11]</a>.</p> | |
| <div class="figure"> | |
| <div style="text-align: left;"> | |
| <pre> | |
| <target name="postBuild"> | |
| <property name="UpdateSiteStagingLocation" value="${buildDirectory}/updateSite"/> | |
| <property name="sitePackagePrefix" value="org.rubypeople.updatesite"/> | |
| <antcall target="generateUpdateSite"/> | |
| </target> | |
| <target name="generateUpdateSite"> | |
| <!-- Create the directory structure --> | |
| <mkdir dir="${UpdateSiteStagingLocation}"/> | |
| <mkdir dir="${UpdateSiteStagingLocation}/features"/> | |
| <mkdir dir="${UpdateSiteStagingLocation}/plugins"/> | |
| <!-- Build the jar files --> | |
| <antcall target="allElements"> | |
| <param name="genericTargets" value="${builder}/customTargets.xml"/> | |
| <param name="target" value="updateSiteExport"/> | |
| </antcall> | |
| <antcall target="copySiteXmlFromCvs"/> | |
| <antcall target="createNightlyBuildSiteXml"/> | |
| </target> | |
| <target name="updateSiteExport"> | |
| <ant antfile="build.xml" dir="${buildDirectory}/features/${id}/" target="build.update.jar"> | |
| <property name="feature.destination" value="${UpdateSiteStagingLocation}/features"/> | |
| <property name="plugin.destination" value="${UpdateSiteStagingLocation}/plugins"/> | |
| </ant> | |
| </target> | |
| <target name="copySiteXmlFromCvs" unless="isNightlyBuild"> | |
| <!-- connect to CVS and fetch site.xml, copy to ${UpdateSiteStagingLocation}/site.xml afterwards --> | |
| </target> | |
| <target name="createNightlyBuildSiteXml" if="isNightlyBuild"> | |
| <!-- create ${UpdateSiteStagingLocation}/site.xml which contains only the nighlty build version --> | |
| </target> | |
| </pre> | |
| </div> | |
| <div class="figure-caption"> | |
| <span class="figure-number">Fig 11</span>. Building for update site | |
| </div> | |
| </div> | |
| <h2>Part 2 - Automated Tests</h2> | |
| <p>After the deliverable has been created the wish may arise to deploy it | |
| and to run a test suite with unit and integration tests. The reasons to do | |
| this automatically as well and present the results along with the | |
| deliverable are manifold:</p> | |
| <ul> | |
| <li>find integration errors, run the tests in different | |
| configurations</li> | |
| <li>give a hint on the quality of the code, particularly useful for | |
| nightly builds</li> | |
| <li>run the tests in a defined environment as opposed to the workbench of | |
| the developer</li> | |
| </ul> | |
| <p>Fortunately, Eclipse provides a framework for test automation, which can | |
| also be leveraged for test automation of arbitrary Eclipse features. The | |
| test results of every Eclipse build are publicly available in the Eclipse | |
| download directories; see <a href="#discussionUpdateSiteBuild">13</a> for | |
| the test results of the 3.0.2 build.</p> | |
| <h3>Eclipse Test Framework</h3> | |
| <p>For running the tests on your PC, get the | |
| eclipse-Automated-Tests-<version>.zip, which contains a zip file with | |
| the unit tests (eclipse-junit-tests-<version>.zip), shell scripts, | |
| build files and documentation. The steps for running the tests are | |
| described in the file testFramework.html (<a href="#testFramework">14</a>). | |
| Basically the shell script runtests starts up a new AntRunner Eclipse | |
| instance which executes one of the targets of the test.xml build file. | |
| Therefore an eclipse installation must exist in the eclipse subdirectory, | |
| which is called the build host in the following. If there is no build host | |
| installation, the script tries to unzip an SDK zip which it assumes to be | |
| the same directory. In addition to that the script extracts the | |
| org.eclipse.test plug-in from the eclipse-junit-tests-<version>.zip | |
| into the build host installation.<br> | |
| <br> | |
| In order to run the some of the tests of the JDT, the following steps are | |
| necessary:</p> | |
| <ol> | |
| <li>Download eclipse-Automated-Tests-3.0.2.zip (<a href= | |
| "#eclipseAutomatedTests">15</a>) and unzip to | |
| $ECLIPSE_AUTOMATED_TESTS</li> | |
| <li>Copy eclipse-SDK-3.0.2 to $ECLIPSE_AUTOMATED_TESTS</li> | |
| <li>cd to $ECLIPSE_AUTOMATED_TESTS and type "runtests.bat jdtui"</li> | |
| </ol> | |
| <p>The last step executes the non-interactive UI tests for the JDT (there | |
| are also interactive UI Tests which require the interaction of a test | |
| person to assure the layout and interactive behaviour of dialogs for | |
| example). Although the tests are non-interactive you will watch a workbench | |
| come up and during the execution of the test suite you can witness projects | |
| being created and closed, editors being opened and so on. After the test | |
| run has finished, the test results will be placed in | |
| $ECLIPSE_AUTOMATED_TESTS/results in html and xml format.<br> | |
| <br> | |
| While the tests run, we can have look behind the scenes. Fig. 12 lists the | |
| build files for test automation; Fig. 13 shows the interaction between | |
| them. At first the runtests script creates the build host and launches an | |
| Eclipse instance as AntRunner. The AntRunner executes the jdt target of | |
| test.xml. During the process another eclipse-installation will take place | |
| in $ECLIPSE_AUTOMATED_TESTS/test-eclipse, called the test host in the | |
| following. The test host also consists of the provided SDK and the full | |
| content of eclipse-junit-tests-3.0.2.zip. A test host instance is then | |
| launched, with the application type org.eclipse.test.uitestapplication | |
| (target uitest in library.xml, see below). The class name of the test suite | |
| is passed to the uitestapplication. After the test suite has completed, the | |
| test results can be found in $ECLIPSE_AUTOMATED_TESTS/results.</p> | |
| <div class="figure"> | |
| <center style="margin-bottom: 1em;"> | |
| <table class="contentTable" cellspacing="2"> | |
| <tbody> | |
| <tr> | |
| <th>file name</th> | |
| <th>location</th> | |
| <th>description</th> | |
| </tr> | |
| <tr> | |
| <td><b>test.xml</b></td> | |
| <td>unzip location of eclipse-Automated-Tests.zip</td> | |
| <td>This script provides the entry point for testing, the | |
| runtests target</td> | |
| </tr> | |
| <tr> | |
| <td><b>test.xml</b></td> | |
| <td>plug-in directory of the test suite to be run</td> | |
| <td>Must provide a run target. Main purpose is to set properties | |
| and delegate to the ui-test target in library.xml. After the | |
| tests have run the collect target in library is called to create | |
| the result files. A skeleton can be found in <a href= | |
| "#testFramework">14.</a> </td> | |
| </tr> | |
| <tr> | |
| <td><b>library.xml</b></td> | |
| <td>plugins/org.eclipse.test, delivered in | |
| eclipse-junit-tests-<version>.zip, which itself is part of | |
| eclipse-Automated-Tests-<version>.zip</td> | |
| <td>This build script contains the eclipse-test target which | |
| launches a new eclipse instance within which the tests will be | |
| executed. Tests can be run with or without UI.</td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| </center> | |
| <div class="figure-caption"> | |
| <span class="figure-number">Fig 12</span>. Files for controlling the | |
| test process | |
| </div> | |
| </div> | |
| <br> | |
| <br> | |
| <br> | |
| <div class="figure"> | |
| <img style="width: 861px; height: 554px;" alt= | |
| "Interaction Diagram for the test process" src= | |
| "runTestsInteractionDiagram.png"><br> | |
| <div class="figure-caption"> | |
| <span class="figure-number">Fig 13</span>. Script interaction for the | |
| test process | |
| </div> | |
| </div> | |
| <h3>Automate Tests for your Plug-In</h3> | |
| <p>Now it is time to think about the effort to automate the tests for your | |
| plug-in. At the time I automated the tests for RDT, the tests resided in | |
| extra plug-ins and there was an AllTests suite, which gathered all the | |
| tests. With these preconditions, there were 3 steps on the road to test | |
| automation:</p> | |
| <ul> | |
| <li>Build a deployable which includes the tests</li> | |
| <li>Add a test.xml file in the plug-in, which contains the AllTests | |
| suite</li> | |
| <li>Add post-build behavior in customTargets.xml</li> | |
| </ul> | |
| <h4>Build a deployable which includes the tests</h4> | |
| <p>Because the deliverable for your plug-in (the zip file or update site | |
| files) should not contain the tests, another zip file for the tests must be | |
| created, called test deliverable in the following. If you followed the | |
| pattern of the Eclipse plug-ins and created a tests plug-in project for | |
| each of your plug-ins, this can easily be achieved. If there is more than | |
| one test plug-in project, a test feature can be created to bundle them. | |
| Therefore you can add a feature project. Alternatively, if you want to keep | |
| the number of projects small and do not have the need to create the feature | |
| interactively from the feature manifest file, you can add a subdirectory to | |
| the existing feature project. The map file can then be used to customize | |
| the fetch process to create a feature directory with the content of the | |
| subdirectory. An example is given in the first line of Fig. 14.</p> | |
| <div class="fileContent"> | |
| feature@org.rubypeople.rdt-tests=HEAD,:ext:cvs.sf.net:/cvsroot/rubyeclipse,,org.rubypeople.rdt-feature/unit-tests-feature<br> | |
| plugin@org.rubypeople.rdt.ui.tests=HEAD,:ext:cvs.sf.net:/cvsroot/rubyeclipse,<br> | |
| plugin@org.rubypeople.rdt.debug.core.tests=HEAD,:ext:cvs.sf.net:/cvsroot/rubyeclipse,<br> | |
| ...<br> | |
| <div class="figure-caption"> | |
| <span class="figure-number">Fig 14</span>. Section from rdt.map for | |
| test feature | |
| </div> | |
| </div> | |
| <p>Building the test deliverable is identical to building the deliverable | |
| itself. If you can use the same build properties as for the deliverable, | |
| just add an additional entry to the allElements target in | |
| customTargets.xml. Fig. 15 shows how the allElements target is adapted for | |
| RDT in order to create the deliverable and test deliverable in one | |
| step.</p> | |
| <div class="fileContent"> | |
| <pre> | |
| <target name="allElements"><target name="allElements"> | |
| ... | |
| <ant antfile="${genericTargets}" target="${target}" > | |
| <property name="type" value="feature" /> | |
| <property name="id" value="org.rubypeople.rdt-tests" /> | |
| </ant> | |
| </target> | |
| <target name="postBuild"> | |
| <antcall target="test"></antcall> | |
| </target> | |
| <target name="test"> | |
| <echo message="Setting up tests in ${eclipseAutomatedTestHome}"/> | |
| <copy file="${buildDirectory}/${buildLabel}/org.rubypeople.rdt-${buildId}.zip" tofile="${eclipseAutomatedTestHome}/eclipse-SDK-RDT-${buildId}.zip" /> | |
| <copy file="${buildDirectory}/${buildLabel}/org.rubypeople.rdt-tests-${buildId}.zip" tofile="${eclipseAutomatedTestHome}/eclipse-junit-tests-rdt-${buildId}.zip" /> | |
| <ant antfile="${eclipseAutomatedTestHome}/test.xml" target="runtests" dir="${eclipseAutomatedTestHome}"> | |
| <property name="os" value="${baseos}" /> | |
| <property name="ws" value="${basews}" /> | |
| <property name="arch" value="${basearch}" /> | |
| <property name="testPlugin" value="org.rubypeople.rdt.tests.all_0.5.0" /> | |
| <property name="report" value="org.rubypeople.rdt.tests.all" /> | |
| </ant> | |
| </target> | |
| </pre> | |
| <div class="figure-caption"> | |
| <span class="figure-number">Fig 15</span>. Targets from | |
| customTargets.xml for testing | |
| </div> | |
| </div> | |
| <h4>Add a test.xml</h4> | |
| <p>A test.xml file must exist for every test plug-in you want to run. | |
| Because every test run starts up a new eclipse instance, it is convenient | |
| to have a plug-in which bundles all the tests into a single AllTests suite. | |
| Then there is only one test run and there must only be one test.xml file | |
| maintained. A template for such a test.xml file can be found in <a href= | |
| "#testFramework">14</a>. Fig. 16 shows important targets of the test.xml | |
| for the RDT plug-in containing the AllTests suite. The entry point is the | |
| run target, which is called from ${eclipseAutomatedTestHome}/test.xml. Its | |
| prerequisites are init, suite and cleanup. The suite target calls ui-test | |
| in library.xml with the necessary properties to start up the test host and | |
| run TS_RdtAllTests.</p> | |
| <div class="fileContent"> | |
| <pre> | |
| <target name="init"> | |
| <tstamp/> | |
| <delete> | |
| <fileset dir="${eclipse-home}" includes="org*.xml"/> | |
| </delete> | |
| </target> | |
| <!-- This target defines the tests that need to be run. --> | |
| <target name="suite"> | |
| <property name="rdt-folder" value="${eclipse-home}/rdt_folder"/> | |
| <delete dir="${rdt-tests-workspace}" quiet="true"/> | |
| <ant target="ui-test" antfile="${library-file}" dir="${eclipse-home}"> | |
| <property name="data-dir" value="${rdt-tests-workspace}"/> | |
| <property name="plugin-name" value="${plugin-name}"/> | |
| <property name="classname" value="org.rubypeople.rdt.tests.all.TS_RdtAllTests"/> | |
| <property name="vmargs" value="-Drdt.rubyInterpreter=&quot;${rdt.rubyInterpreter}&quot;"/> | |
| </ant> | |
| </target> | |
| <!-- This target holds code to cleanup the testing environment after --> | |
| <!-- after all of the tests have been run. You can use this target to --> | |
| <!-- delete temporary files that have been created. --> | |
| <target name="cleanup"> | |
| </target> | |
| <!-- This target runs the test suite. Any actions that need to happen --> | |
| <!-- after all the tests have been run should go here. --> | |
| <target name="run" depends="init,suite,cleanup"> | |
| <ant target="collect" antfile="${library-file}" dir="${eclipse-home}"> | |
| <property name="includes" value="org*.xml"/> | |
| <property name="output-file" value="${plugin-name}.xml"/> | |
| </ant> | |
| </target> | |
| </pre> | |
| <div class="figure-caption"> | |
| <span class="figure-number">Fig 16</span>. Important targets of | |
| org.rubypeople.rdt.tests.all/test.xml<br> | |
| </div> | |
| </div> | |
| <h4>Add post-build behavior in customTargets.xml</h4> | |
| <p>Fig. 15 shows the test target of customTargets.xml, which is executed in | |
| the PostBuild phase of the build process. The property | |
| eclipseAutomatedTestHome is set to the directory into which | |
| eclipse-Automated-Tests-<version>.zip has been extracted. The first | |
| step in the test target is to copy the two deliverables into this | |
| directory, following a naming schema which is given in | |
| ${eclipseAutomatedTestHome}/test.xml. By using these names, the runtests | |
| target of test.xml extracts the deliverables into the test host | |
| installation (in ${eclipseAutomatedTestHome}/test-eclipse/eclipse). The | |
| second step is to call the runtests target of | |
| ${eclipseAutomatedTestHome}/test.xml. The property testPlugin defines which | |
| tests to run and the report property defines the name of the generated | |
| report.</p> | |
| <p>Compared to the example above, where we ran the tests jdt ui, there is | |
| no need to create the build host in $ECLIPSE_AUTOMATED_TESTS/eclipse, | |
| because the target runtests in test.xml is directly called from the | |
| postbuild target in customTargets.xml. So the build host for the automatic | |
| build is reused as build host for the automatic tests. Fig. 17 shows the | |
| difference compared to Fig. 13.</p> | |
| <div class="figure"> | |
| <img alt="Interaction Diagram for the test process" src= | |
| "runTestsRdtInteractionDiagram.png"><br> | |
| <div class="figure-caption"> | |
| <span class="figure-number">Fig 17</span>. Script interaction for the | |
| test process<br> | |
| </div> | |
| </div> | |
| <blockquote> | |
| <p><img src="../images/tip.gif" height="13" width="62">PDE JUnit tests | |
| open up a workbench window. If you run your tests on a remote *nix box, | |
| you can use Xvfb (X virtual frame buffer) to provide a dummy environment | |
| for displaying windows.</p> | |
| </blockquote> | |
| <h4>Run the RDT tests</h4> | |
| <p>If you want to run the RDT tests, follow the instructions above for | |
| building RDT and set the following additional properties in run.bat or | |
| run.sh:</p> | |
| <ul> | |
| <li>unset dontRunTests</li> | |
| <li>set eclipseAutomatedTestHome to the directory into which you | |
| extracted eclipse-Automated-Tests-3.0.2.zip</li> | |
| <li>unset rubyInterpreter if you don't have ruby installed (which will | |
| result in failed tests)</li> | |
| </ul> | |
| <p>After you call run.bat or run.sh the tests will be executed in the | |
| postBuild phase. If you want to run the tests separately, you can insert | |
| the build target after the -build property in the antRunner command | |
| line:</p> | |
| <pre> | |
| %vm% -cp %eclipseDir%\startup.jar ... org.eclipse.core.launcher.Main -application org.eclipse.ant.core.antRunner -buildfile %buildfile% postBuild -data ... | |
| </pre> | |
| <h1>Conclusion</h1> | |
| <p>Hopefully this article could help you in setting up project automation | |
| for your Eclipse plug-in project. It has shown the automation mechanisms | |
| used in building Eclipse itself and how they are leveraged to build and | |
| test arbitrary plug-ins automatically with a single command. Further | |
| project automation can be achieved from the inside or from the outside: | |
| From the inside by using the hooks provided in the build files for | |
| activities like enhanced reporting. From the outside by calling the build | |
| command as part of a broader build process from tools like CruiseControl or | |
| Maven.<br> | |
| For the discussion of questions about this article and experiences with | |
| Eclipse build and test automation in general, I'd like to invite you to the | |
| RDT developer wiki [<a href="#feedbackPage">17</a>] or to e-mail me [<a | |
| href="#mbarchfeContact">18]</a>.</p> | |
| <h1>Acknowledgments</h1> | |
| <p>I would like to thank Sonia Dimitrov and Pascal Rapicault for their | |
| article draft, which I have weaved into this article. Many thanks also to | |
| Pat McCarthy for his valuable comments.</p> | |
| <h3>Reference</h3> | |
| <table> | |
| <tbody> | |
| <tr> | |
| <td valign="top"><a name="pdeHelpBuildProperties">[1]</a> </td> | |
| <td><a href= | |
| "http://help.eclipse.org/help30/topic/org.eclipse.pde.doc.user/guide/pde_feature_generating_build.htm" | |
| class="referenceLink">PDE Help on build.properties</a>, Eclipse 3.0 | |
| Help</td> | |
| </tr> | |
| <tr> | |
| <td valign="top"><a name="pdeHelpGenAnt">[2]</a> </td> | |
| <td><a href= | |
| "http://help.eclipse.org/help30/topic/org.eclipse.pde.doc.user/guide/pde_feature_generating_ant.htm" | |
| class="referenceLink">PDE Help on Generating Build Files</a>, | |
| Eclipse 3.0 Help</td> | |
| </tr> | |
| <tr> | |
| <td valign="top"><a name="bugsHeadlessInvokation">[3]</a> </td> | |
| <td><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=65146" | |
| class="referenceLink">Generated feature build scripts and headless | |
| invokation</a> , Eclipse Bugs</td> | |
| </tr> | |
| <tr> | |
| <td valign="top"><a name="pdeHelpGenCommandLine">[4]</a> </td> | |
| <td><a href= | |
| "http://help.eclipse.org/help30/index.jsp?topic=/org.eclipse.pde.doc.user/guide/pde_feature_generating_antcommandline.htm" | |
| class="referenceLink">PDE Help on headless build</a> , Eclipse 3.0 | |
| Help</td> | |
| </tr> | |
| <tr> | |
| <td valign="top"><a name="eclipsExamples">[5]</a> </td> | |
| <td><a href= | |
| "http://www.eclipse.org/downloads/download.php?file=/eclipse/downloads/drops/R-3.0-200406251208/eclipse-examples-3.0-win32.zip" | |
| class="referenceLink">eclipse-examples-3.0-win32.zip</a> , Eclipse | |
| Download Area</td> | |
| </tr> | |
| <tr> | |
| <td valign="top"><a name="eclipsebuilderReadme">[6]</a> </td> | |
| <td><a href= | |
| "http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.releng.eclipsebuilder/readme.html?rev=1.24" | |
| class= | |
| "referenceLink">org.eclipse.releng.eclipsebuilder/readme.html</a> , | |
| Eclipse CVS</td> | |
| </tr> | |
| <tr> | |
| <td valign="top"><a name="sdkExamplesBuildFiles">[7]</a> </td> | |
| <td><a href= | |
| "http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/org.eclipse.releng.eclipsebuilder/sdk.examples" | |
| class= | |
| "referenceLink">org.eclipse.releng.eclipsebuilder/sdk.examples</a>, | |
| Eclipse CVS</td> | |
| </tr> | |
| <tr> | |
| <td valign="top"><a name="jdtFeature">[8]</a> </td> | |
| <td><a href= | |
| "http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt-feature/" | |
| class="referenceLink">JDT feature</a> , Eclipse CVS</td> | |
| </tr> | |
| <tr> | |
| <td valign="top"><a name="pdeScripts">[9]</a> </td> | |
| <td><a href= | |
| "http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.pde.build/scripts" | |
| class="referenceLink">org.eclipse.pde.build/scripts</a>, Eclipse | |
| CVS</td> | |
| </tr> | |
| <tr> | |
| <td valign="top"><a name="buildBootstrapFilesRdt">[10]</a> </td> | |
| <td><a href= | |
| "http://cvs.sourceforge.net/viewcvs.py/rubyeclipse/org.rubypeople.rdt.build/bootstrap/"> | |
| RDT bootstrap files for headless build</a>, RDT CVS</td> | |
| </tr> | |
| <tr> | |
| <td valign="top"><a name="discussionUpdateSiteBuild">[11]</a> </td> | |
| <td><a href= | |
| "http://dev.eclipse.org/newslists/news.eclipse.platform/msg25629.html" | |
| class="referenceLink">Way to automatically build for update | |
| site?</a> , Eclipse News</td> | |
| </tr> | |
| <tr> | |
| <td valign="top"><a name="usingPDEBuild">[12]</a> </td> | |
| <td><a href= | |
| "http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.pde.build/notes/usingPDEBuild.html?rev=1.8" | |
| class="referenceLink">Using PDE Build</a>, Eclipse CVS</td> | |
| </tr> | |
| <tr> | |
| <td valign="top"><a name="eclipseTestResults">[13]</a> </td> | |
| <td><a href= | |
| "ftp://download.eclipse.org/R-3.0.2-200503110845/testresults" class= | |
| "referenceLink">Eclipse Test Results for 3.0.2</a>, Eclipse Download | |
| Area</td> | |
| </tr> | |
| <tr> | |
| <td valign="top"><a name="testFramework">[14]</a> </td> | |
| <td><a href= | |
| "ftp://download.eclipse.org/R-3.0.2-200503110845/testframework.html" | |
| class="referenceLink">testframework.html</a>, Eclipse Download | |
| Area</td> | |
| </tr> | |
| <tr> | |
| <td valign="top"><a name="eclipseAutomatedTests">[15]</a> </td> | |
| <td><a href= | |
| "http://www.eclipse.org/downloads/download.php?file=/eclipse/downloads/drops/R-3.0-200406251208/eclipse-Automated-Tests-3.0.zip" | |
| class="referenceLink">eclipse-Automated-Tests-3.0.2.zip</a>, Eclipse | |
| Download Area</td> | |
| </tr> | |
| <tr> | |
| <td valign="top"><a name="generateSourceFeatureBug">[16]</a> </td> | |
| <td><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=86299" | |
| class="referenceLink">generate.feature and building using export | |
| button in feature.xml</a> , Eclipse Bugs</td> | |
| </tr> | |
| <tr> | |
| <td valign="top"><a name="feedbackPage">[17]</a> </td> | |
| <td><a href="http://213.203.244.123/wiki/Automatic_Build.wiki.phtml" | |
| class="referenceLink">feedback page</a>, RDT developer wiki</td> | |
| </tr> | |
| <tr> | |
| <td valign="top"><a name="mbarchfeContact">[18]</a> </td> | |
| <td><a href="http://sourceforge.net/users/mbarchfe/" class= | |
| "referenceLink">contact</a>, user page at sf.net</td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| <p><small>ref: <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=87151">bug | |
| 87151</a></small></p> | |
| <p><small>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.</small></p> | |
| </body> | |
| </html> | |