Updated PDE Build and Test Example

I’ve just spent some time updating my example showing how to set up PDE Build and the Eclipse Testing Framework. I’ve generally cleaned things up and I’m now creating the test environment in the correct way.

As a special bonus, I’ve also thrown in coverage analysis using EMMA. And before people ask, yes I have tried to use Clover with PDE Build, but have had little luck due to Clover’s dependence on a specialized Java complier. If anyone has gotten this to work, I’d love to hear about it.

And finally, I had to change this example to use a test plug-in instead of a test fragment. For some reason when running Eclipse 3.4 (maybe related to p2?), the ETF is not finding tests in fragments. If anyone has any ideas here as well, please let me know.

You can download the new example here.

NOTE: I’ve discovered that the EMMA instrumentation task fails if you’re running the script inside of Eclipse and you have spaces in your workspace path. Avoid spaces in your path and you should be good to go.

Advertisements

47 Responses to Updated PDE Build and Test Example

  1. Kevin says:

    Thanks so much for your posts. We are in need of this automation. I am trying to follow your example. It gets to the test framework target, calling core-test and then it can’t find the example project classes.

    java.lang.NoClassDefFoundError: com/rcpquickstart/helloworld/HelloWorldModel

    I get this whether I run from Eclipse or the command line.

    Running WinXP, Java 1.6.

    I can send the full log if you are interested.
    Thanks,
    Kevin

  2. Patrick says:

    Hi Kevin,

    Sure, can you send the full log to the email address in the “About Me” section on the top right? And can you also tell me what changes you made to get the script running in your environment?

    The only difference I can see right now is that I’m running Java 1.5 instead of 1.6.

    — Patrick

  3. Patrick says:

    I’ve responded to Kevin via email, but I wanted to let everyone else know that it is necessary to place the emma.jar file in the lib/ext directory of the JRE that is running the build. This makes the EMMA classes accessible to the Eclipse Testing Framework via the OSGi parent classloader.

    I’ve updated the readme file to include this step.

    — Patrick

  4. meabloga says:

    Patrick, the spaces problem is fixed in Eclipse 3.5M1… with the addition of Ant 1.7.1 that has the bug fix. It caused me nothing but grief a couple days ago when debugging the issue πŸ™‚

    See:

    https://issues.apache.org/bugzilla/show_bug.cgi?id=42222
    https://bugs.eclipse.org/bugs/show_bug.cgi?id=208611

  5. Patrick says:

    Hi Chris,

    Thanks for the heads up. I suspected that might be the reason, but wasn’t sure. It will definitely be nice to not have to worry about this anymore in 3.5.

    — Patrick

  6. Zuber says:

    Patrick,

    The build doesn’t create .exe launcher for the product and the same works fine while Exporting product from eclipse.
    Can you please tell me how to generate exe from product file using your build script?

  7. Patrick says:

    Hi Zuber,

    Have you extracted the RCP Delta Pack into your target platform? During an automated build the launcher comes from launcher fragments only found in the Delta Pack. When building inside the IDE, the build just grabs the exe from your Eclipse install.

    — Patrick

  8. Frode says:

    Hi Patrick,

    Thanks for this great example! It worked as advertised when I followed your instructions to the letter. Running from Ant standalone also worked, but then I added code to build.xml to exclude class files from being copied to the build directory:

    The build failed. PDE build was trying to build the com.rcpquickstart.helloworld.test.feature first, which obviously won’t work as the com.rcpquickstart.helloworld.test plugin depends on com.rcpquickstart.helloworld. This left me confused as I expected PDE build to sort out the build order.

    I found and news post indicating that PDE Build sorts out the build order of plugins within a feature, but features themselves are built in the order they are specified. Am I correct ,and is this documented somewhere?

    Removing the helloworld.test.feature from the helloworld.feature and adding it to helloworld.product definition (after the helloworld.feature) gets the order right, but I don’t like the smell of this. Is there a better way?

    – Frode

  9. Patrick says:

    Hi Frode,

    Yes, it appears that the order of features in the product configuration determines the build order. I experimented with making the test feature depend on the non-test feature, but that didn’t work either.

    I agree that it doesn’t smell too good, but unless I’m missing something this is the way it works.

    — Patrick

  10. Nihal says:

    Hey Patrick,

    We were able to get clover working. It’s complicated, but not impossible to do. Here’s what you need to do:

    First I’m assuming you’ve copied the feature to be built to a directory structured in the following way:

    /eclipse – the root folder you’re using to build the feature
    /eclipse/plugins – contains the plugins within the feature
    /eclipse/features – contains your feature

    Lets say for this example you are building featureA that only has one plugin named pluginA. The following is geared toward building with Apache Ant.

    1.) Back up the source. I.e. Run the copy task copying “/eclipse/plugins/pluginA/src” to “/eclipse/plugins/pluginA/instrumented_src”. We need to have the original source as opposed to the instrumented source when generating code coverage data, otherwise you’ll see instrumented source when you build coverage reports πŸ™‚

    2.) Instrument the source. I.e. execute the com.cenqua.clover.CloverInstr class using the java task. This class is available from your clover installation. I’m using Clover 1.3.13. In later versions the task name may have changed. The arguments are as follows:

    “-jdk15 -i /eclipse/clover.db -s /eclipse/plugins/pluginA/instrumented_src -d /eclipse/plugins/pluginA/src”

    Obviously, if your source isn’t source level 1.5, don’t add the “-jdk15”. See http://www.cenqua.com/clover/doc/cli/cloverinstr.html for more info.

    3.) Make the clover class files available to the plugin for compilation.

    a.) Modify the plugin’s manifest adding in the clover plugin. You need to do this because the instrumented source references clover classes. ***See note below about how to get the clover plugin***

    So, append “,com.cenqua.clover” to the “Require-Bundle” property of the file /eclipse/plugins/pluginA/META-INF/MANIFEST.MF. You may have to find some custom ant task to do this.

    b.) Copy the clover plugin jar into /eclipse/plugins. Again, this is to make the clover classes available to the instrumented source during compilation.

    4.) Compile the feature using the RCP build, and run your automated tests. These are both way outside the scope of this post, so I’m not going to cover them here. Exercising the tests should change your coverage.db file.

    5.) Generate the clover report based on your /eclipse/coverage.db file.

    ***
    Ok, now about the clover plugin. Basically, the clover jar is obfuscated such that you cannot reliably extract files from it (or so I’ve found). This prevents you from turning it into a plugin using Eclipse’s > New Project > Plug-in from existing JAR archives.

    However, you can add a MANIFEST.MF to the clover jar’s META-INF folder thus turning it into a plugin. Really all we’re doing here is making the clover classes available to the plugin during compilation. Maybe there’s a better way to do this, but I’ve found that you can turn it into a plugin and copy it to the /eclipse/plugins folder for compilation.

    Also, since I’m lazy and didn’t want to create that MANIFEST.MF file by hand, I used the aforementioned wizard (New Project > Plug-in from existing JAR archives) to generate the MANIFEST.MF for me, which I then copied into the clover jar. Be sure to export all the correct packages within the clover plugin (I just exported all of them). I believe there is actually a clover plugin for Eclipse, but I wanted to be absolutely sure that I was compiling pluginA against the exact version of clover I used to instrument the source.
    ***

    That’s it. Like I said, complicated, but not impossible. Maybe someone can streamline it further.

  11. Patrick says:

    Hi Nihal,

    Wow! That was complicated, but I’m glad you got it working. I’m sure this will come in very handy to some.

    Thanks for posting the instructions.

    — Patrick

  12. […] Clover with PDE Build In a previous post I mentioned that I had not yet found a way to use Clover to perform coverage analysis when running […]

  13. Isnt there any other method than copinying whole SDK? Its too slow. I am considering symlinks on unix (faster) but I would prefer modifying the script that tests will use some different metadata directory (in tmp folder that is cleaned on each run).

  14. Hi,

    I am getting “java.lang.NoClassDefFoundError: junit/framework/TestListener” while running the test. This bundle has plugin dependency on junit bundle. I cannot find the problem 😦

  15. Patrick says:

    Hi Lukas,

    As for the SDK, your approaches sound like they might work and I’d be interested to know what you decide on. Obviously, any approach that starts with a clean Eclipse SDK will work.

    I’m not sure why you’re getting the exception. Have you made many changes to the example or are you trying to run it as is? Is the exception thrown in the Ant output or the test output? If you’d like to send me the full stack trace, I’d be happy to look at it.

    — Patrick

  16. Gabe says:

    What if you have multiple plugins that have different dependencies on Eclipse plugins. I found myself adding more and more plugins into the “Plugins and Fragments” section of the main feature.xml. For example I added org.eclipse.jface.text and then found that had a dependency on org.eclipse.text. Should each of my plugins have their own feature? Would be great if you could add a second plugin to your example to demonstrate this.

    Thanks for everything so far though! Would not have got this far without it.

  17. Patrick says:

    Hi Gabe,

    Organizing third party plug-ins into features can be a challenge. I think the key is to always think about features from a build and update point of view. In particular, what plug-ins are likely to be built and updated at the same time.

    One simple solutions is to simply place all third party plug-ins that are not part of the org.eclipse.rcp feature into a separate feature of their own. Another solutions might be to create a feature for Eclipse third-party plug-ins (they usually all get updated at the same time) and a second feature for other third-party plug-ins.

    Hope this helps,

    — Patrick

  18. Gabe says:

    Any idea how to get junit4 tests to run?

    I followed all the way through the example and then updated my project only to get a “No tests found” message…

  19. Patrick says:

    Hi Gabe,

    Unfortunately, it’s not possible at the moment. Check out this Bugzilla entry and add your voice to the chorus asking for a fix!

    https://bugs.eclipse.org/bugs/show_bug.cgi?id=153429

    — Patrick

  20. Kristof says:

    Hi,

    I tried this from within a 3.4.1 eclipse RCP SDK on MacOS. Below are the error messages I got while property equinoxLauncherPluginVersion was set to 1.0.101.R34x_v20080819. It seems something is stubbornly pointing to a different equinox launcher bundle. Any idea

    [java] /Tools/eclipse-rcp/plugins/org.eclipse.pde.build_3.4.1.R34x_v20080805/scripts/productBuild/productBuild.xml:28: The following error occurred while executing this line:
    [java] /Tools/eclipse-rcp/plugins/org.eclipse.pde.build_3.4.1.R34x_v20080805/scripts/build.xml:64: The following error occurred while executing this line:
    [java] /Tools/eclipse-rcp/plugins/org.eclipse.pde.build_3.4.1.R34x_v20080805/templates/headless-build/customTargets.xml:12: The following error occurred while executing this line:
    [java] /Tools/eclipse-rcp/plugins/org.eclipse.pde.build_3.4.1.R34x_v20080805/scripts/productBuild/allElements.xml:10: The following error occurred while executing this line:
    [java] /Tools/eclipse-rcp/plugins/org.eclipse.pde.build_3.4.1.R34x_v20080805/scripts/genericTargets.xml:88: Unable to find plug-in: org.eclipse.equinox.launcher_1.0.100.v20080509-1800. Please check the error log for more details.

  21. Patrick says:

    Hi Kristof,

    Is the application you’re building based on 3.4.1 as well? Have you added the RCP Delta Pack to your target platform? If these aren’t the problems, feel free to email me your scripts and I’ll take a look.

    — Patrick

  22. Kristof says:

    Hi,

    sorry, was mixing 3.4 RCP and delta pack with a 3.4.1 SDK.

  23. Johannes says:

    Hi Patrick,

    nice Blog! One Question, is it possible in the meantime to load testcases from fragments? I see no other way of doing this, since we cover a huge amount of test for non-published classes, this can only be done with fragments as far as i can see.. How would one resolve this problem?

    Thanks in advance

    johannes

  24. Patrick says:

    Hi Johannes,

    If you’re asking how to collect and run tests contained in fragments, there are a few possible approaches. One is to use reflection to dynamically create a master test suite for the fragments. Another similar option is to use what I call a test collector to harvest all of the tests. I’ve covered these options in a few posts on this blog:

    http://rcpquickstart.com/2007/06/20/unit-testing-plug-ins-with-fragments/
    http://rcpquickstart.com/2008/06/12/running-unit-tests-for-rcp-and-osgi-applications/

    If this wasn’t what you meant in your question, let me know and I’ll try to answer it again!

    — Patrick

  25. Torsten says:

    Thanks for this example. It helped a lot getting started with automated pde builds.

    I found out that it is possible to replace “-Dosgi.parentClassloader=ext” with “-Dosgi.dev=${absolute.path.to.emma.jar}”. Then you do not have to copy emma.jar into the lib/ext directory.

    – Torsten

  26. Patrick says:

    Hi Torsten,

    Thanks for the tip! It certainly gives you more flexibility than the osgi.parentClassloader argument.

    — Patrick

  27. Parag says:

    Hi Patrick,

    I have a RCP JNLP application where features and plugins are bundled in JARs (not as exploded folders).

    While running the test using ETF, getting following error.

    ———-
    !ENTRY org.eclipse.update.configurator 2009-02-24 18:50:13.306
    !MESSAGE Unable to find feature.xml in directory: C:\temp\PTGDevTools_build\test-eclipse\eclipse\features\com.ebay.xxx.nonui.test.feature_1.0.0.200902241741-78407BsAC_IBz-UcTUtuIgz-If.jar

    !ENTRY org.eclipse.update.configurator 2009-02-24 18:50:13.306
    !MESSAGE Unable to find feature.xml in directory: C:\temp\PTGDevTools_build\test-eclipse\eclipse\features\com.ebay.xxx.core.feature_3.2.0.200902241741-7p817D7sQSMQstHfyHe.jar
    ——————

    According to the error, its not finding the feature.xml because the features are in JAR format.

    is Eclipse Test Framework support only plugins/features with exploded folder format and not with JAR format?

    How can I handle this scenario?

    Thanks,
    Parag

  28. Patrick says:

    Hi Parag,

    Sorry for the delay in getting back to you. I’m on vacation right now and not checking the blog every day.

    It is true that features cannot be in JAR form at runtime. Normally features are extracted during installation but in your case this is not happening so you would need to do it manually. You could add an extra step into the “test” target to extract any features packaged as JARs.

    Here’s a link that discusses this issue:

    http://www.eclipsezone.com/eclipse/forums/t92012.html

    Hope this helps,

    — Patrick

  29. Parag says:

    Thanks Patrick for the answer.

  30. Chris says:

    Hi Patrick,

    First of all … “BIG THANKS” for providing that example. I was struggling with that topic long time and without that sample I still would have problems for sure.

    I have a few comments – maybe they are of use.

    a) At start i couldn’t get it running. I always got complaints that the test runner application is missing.
    The reason was a silly mistake on my side: DON’T take the RCP-SDK, even if you build an RCP application (like my team does). Take the standard “eclipse SDK” (exactly as Patrick said in his readme.txt).

    b) I modified the sample to put the tests into a test source folder of the plugin itself. I know – this makes it more difficult to exclude test code from being packaged. BUT … this doubles the number of jobs I have to configure for my Continuous Integration system (hudson) – and I have to configure those jobs for each branch we build. Right now we have like 20 plugins (rising), and two branches – so that would be 40 additional CI jobs to be maintained.
    This is really nasty work I’d like to avoid. So is there another reason to separate the plugins from their test code beside better packaging and dependency control?

    c) The last comment likely is just a rant, but ….
    is anyone out there as frustrated as I am about this whole topic? Does anyone think this is a “good system”? I mean …. hey – all this effort just to compile / package / unit test some java code?
    Years ago the whole topic was solved already, and reduced to about 5 lines of ANT code.
    Patricks whole sample code would compile / build / test in like 5 seconds – if it were just a “normal” java project.
    Then the eclipse plugin environment comes along – and suddenly the build process gets as complicated as rocket science. The ANT script explodes by a factor of 10 at least, and the whole build cycle takes one minute – even for such a very trivial example (of course including unzipping the SDK … it’s a shame that such tricks are needed on a modern system).

    Oh well – at least I got it running. I can’t imagine though that I would ever recommend building a “normal” application based on RCP again. It simply adds too much overhead to the development process (the complicated and slow build process is just one example of many).

    Ok – sorry for the rant, especially as it is most likely the wrong place to talk about that topic anyways. It’s surely not Patricks “fault” – he just provided the solution, and I am very happy about that.

    Chris

  31. Patrick says:

    Hi Chris,

    You’re welcome. And I understand where you’re coming from, I really do. I hope that the RCP build story gets a lot simpler in the future.

    I’ve started to look at Maven and Tycho, and I’m going to try to blog about this soon.

    http://docs.codehaus.org/display/M2ECLIPSE/Tycho+user+docs

    — Patrick

  32. Johan says:

    Hi Patrik,

    I seem to be having a similar problem as Lukas Zapletal from above (September 30, 2008 at 3:24 pm).

    I’m trying to get a non-RCP PDE build to work, using your example as a code basis. (I’m also using a product definition that is based on features and lists org.eclipse.sdk as a feature for this, as described by Richard Gronback here: https://bugs.eclipse.org/bugs/show_bug.cgi?id=249352).

    Currently, I’m stuck at a point where a JUnit test is being launched, but then fails with “Java Result 13” and the following error message:

    java.lang.ClassNotFoundException: junit.framework.TestListener

    I know, however, by reading from Java verbose output, that both the Class org.junit are loaded. The following message is also logged:

    !MESSAGE Could not install bundle plugins/org.junit_3.8.2.v20080602-1318/ Bundle “org.junit” version “3.8.2.v20080602-1318” has already been installed from: reference:file:plugins/org.junit_3.8.2.v20080602-1318

    (which I do not judge as a problem causing trouble).

    The generated eclipse target (including my features) seems to be fine, it can be launched and everything I expect the find there exists.

    Do you have a clue what the problem could be here?

    Thanks in advance,
    Johan

  33. Patrick says:

    Hi Johan,

    Debugging this stuff is a real pain, but I guess I don’t need to tell you that.. And I’m not sure why you’re getting that particular error.

    My approach to this is always to start with a running build and then move one step at a time to where you want to be. So in this case, do you have a successful build working with the sample projects?

    If so, if there is any way to gradually move your build into the sample build structure, that’s what I would do. For instance, try to move your product into the build but with as few features as possible. Then try adding one feature at a time.

    I wish I had a more specific answer for you, but I hope this helps.

    — Patrick

  34. Johan says:

    Hi again Patrick,

    thanks a lot for your answer!

    As you suggest, I did start with a running example build – your example :-). But these were some small adaptations I had to make:

    * not to build an RCP application; so I had to specify ‘org.eclipse.ui.ide.workbench’ as the application to be started in the product configuration file
    * not to use Emma, but Cobertura instead (but code coverage really is not the issue)

    What I don’t know for sure is whether only RCP applications can be built using product build, or also non-RCP?

    The build I’m trying to get together really is a minimal set of features, to be exact, just two: “hello-world” and “hello-world.test”. So nothing I could simplify there I believe..

    If you should have any more ideas about this, I’d be very interested in them.

    Thanks again,
    Johan

  35. Johan says:

    Hi,

    for all those who have been struggling with the same problem, I finally found the solution: the eclipse-test-framework-3.4.zip that I was using contains both JUnit 3 and 4. However, version 4 plugin contained no signing information (RSA file). During the build process, the framework contents were successfully copied into the eclipse target platform, overwriting JUnit jars that already existed there. JUnit 4 of the target platform, however, did contain a signing information file! The problem that then arose was that the JUnit classes would not run with the wrong signing info. My solution was then to just remove JUnit 4 from the testing framework (I’m using version 3 anyway, since 4 seems not to work with PDE builds).

    Johan

  36. Patrick says:

    H Johan,

    Thanks for posting this! I’m glad you found the answer and I’m sure it will help others trying to figure this out.

    — Patrick

  37. Govind says:

    Hi Patrick

    I want show busy status while opening dialogs which takes some time in my RCP application.

    How can show animated loading gif image instead of busy cursor.Can u give me some example.

    Thanks in advance.

    Regards
    Govind

  38. Patrick says:

    Hi Govind,

    To display animated images, check out the ImageData section of the SWT snippets page.

    I think a better approach would be to use the regular RCP feedback for long-running operations, which is the conveyer belt in the status bar. To get this effect, you should use the Jobs API (search for “concurrency” in Eclipse Help).

    If you want to lock the UI while the dialog is loading, you can use a UIJob which will run on the UI thread.

    Hope this helps,

    — Patrick

  39. Shami says:

    Hi Patrick,

    Have you gotten any further with Maven/Tycho and RCP builds (that you mentioned you had started playing with)?

    I am starting along this same path, but without huge success yet (unfortunately it is my first experience with Maven…so there is a learning curve on that front).

    I was wondering if you were getting anywhere with your playing. It seems like it would help with the whole JUnit setup and getting the packages that are needed at the right time.

    thanks,
    Shami.

  40. Patrick says:

    Hi Shami,

    I played with Tycho for a bit but I too didn’t get very far. I only spent about an hour on it, though. I have it on my todo list to get back to it at some point, and I agree that a Maven build process for RCP apps would help a lot, especially for running unit tests as you say.

    What issues are you having, if you don’t mind me asking?

    — Patrick

  41. Shami says:

    Hey Patrick,

    I tried using the latest versions of Tycho, both:

    Latest DEV build: 0.3.0-DEV-1819
    and
    Experimental build: 0.4.0-DEV-2233

    I followed the instructions for building a feature based RCP application, but it auto-generates pom.xml files that only generate an update site with the feature/plugin jars. This is a good start, but not a RCP product. (I was just testing using the “Hello World” RCP example that Eclipse can generate…so nothing fancy πŸ™‚

    I had read that you need to keep the product file separate (there are examples in Tycho’s integrated testing for this, so I made my .product file in a separate project directory from my code and changed the packaging to: ‘eclipse-application’. This still did not create a binary product.

    Then I added the following piece to the root pom.xml file so that it actually tried to package up the RCP application as a product:
    ———————

    org.codehaus.tycho
    maven-osgi-packaging-plugin
    ${tycho-version}

    package
    product-export

    product-export

    example.product/example.product

    ———————

    This actually tries to build the application and creates most of the directory structure correctly, but gives a NullPointerException when copying the features.

    I had read on-line in various places that this problem is caused because the product file must be in a separate directory, but I had already moved it to a separate directory and it still gave the NPE.

    So I am leaving it for now, but I was interested if you had gotten any farther or how your experience had gone.

    The Tycho project is definitely showing a lot of progress and could really add a lot to opening up the PDE build (black box) but it seems like there are still some issues for actually producing an RCP product.

    later,
    Shami.

  42. Shami says:

    Hey Patrick,

    My xml code got stripped…so I will try with pre tags :). The xml that I added to the top pom.xml to actually build the product was:

    
        
          
            org.codehaus.tycho
            maven-osgi-packaging-plugin
            ${tycho-version}
            
              
                package
                product-export
                
                  product-export
                
                
                  example.product/example.product 
                
              
            
          
        
      
    

    Hope that helps,
    Shami

  43. Patrick says:

    Hi Shami,

    Thanks for the info. I’ll let you know if I have better luck.

    — Patrick

  44. Govind says:

    Hi Patrick

    I have overridden the createWindowContents in my rcp in ApplicationWorkbenchWindowAdvisor for custom layout..

    But on the right side when none of the pages are open the grey area is shown and i guess which is by createEmptyWindowContents method.

    When i try to override the createEmptyWindowContents its not called..

    can u tell me why ??

    Regards
    Govind R

  45. Patrick says:

    It appears that WorkbenchWindow.open() calls the method when there are no pages in the workbench. It’s also called whenever a page closes and there are no other pages open.

    Hope this helps,

    — Patrick

  46. SeB says:

    This a great blob entry and a very good start.
    I have written some more details in my newly created blog (http://eclipsercpdev.blogspot.com/2009/07/automating-unit-tests-for-rcp.html)after strugling a couple of days.

    -SeB-

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: