Tuesday, December 21, 2010

Eclipse to Visual Studio 2010: What I'm Missing

I've recently been spending a lot of my time in Visual Studio 2010. Having been in Eclipse for many years, the transition has been somewhat painful. In no particular order, here are the features that I'm still trying to track down. VS experts, help me out!

  1. Quick Fix - Assign to local variable.  Write the RHS of an assignment statement, then Ctrl+1 to have the IDE suggest/insert a LHS.
  2. Curly brace auto-completion.  When I type the opening brace and hit enter, automatically indent one tab and add a close brace on the following line.
  3. Ctrl-Click for type definition hyperlinking.  Basically, a mouse gesture for Visual Studio's Go To Definition F12. I've been told there is an extension for this??
  4. Ctrl-Click for externalized strings (resources in .NET?).  In Eclipse, when I Ctrl-Click on an externalized message referenced as a static String, I can jump to the properties file directly.
  5. "Flexible" Go To Definition. In Eclipse, if I write some code that calls a method, and I don't have the particular overload parameters sequenced correctly, I can still (typically) jump to the definition of one of the overloads. Since they're typically clustered together in the target type, this is a poor man's way of getting around reading the Javadoc.
  6. (Speaking of Javadoc), Hover over a method to see its NDoc documentation. Reading the commented XML syntax on a method doesn't do it for me.
  7. Link With Editor / Show In.  When I'm jumping around using Go To Definition, I quickly lose track of where (in the resource tree) a particular class is.  In Eclipse, I can toggle and untoggle Link With Editor to highlight the resource in Package Explorer.  How do I select the current editor's file in Solution Explorer?
  8. Synchronize View. This one is a HUGE hole. How the hell do you .NET people sync your code in a sane way??
  9. Multi-Page Editors. I'll qualify this one a bit by saying that I've seen the implementation details of multi-page editors in Eclipse, and there are some definite issues. But the functionality is critical when you have an XML document which also has a graphical editor. (Entity Framework conceptual models, I'm lookin' at you.) Gimme a synchronized two-tab editor so I don't have to keep doing Open With, closing the other editor (can't have both open at the same time, another FAIL), etc.
  10. Outline View in the XML editor.  'Nuff said.
  11. Collapse All / Expand All.  Solution Explorer needs these badly.
  12. File -> Restart. After I install a Visual Studio Extension, I need to restart. Please make this one click, thanks. 
  13. Workspaces.  I really don't know how to explain this one. You can see one of my complaints (relating to Team Explorer) in this post. Another example is that of "recent solutions". Please just keep my last solution open?  What am I missing here?  I need to have separate "threads" of work that are preserved somehow, so I can easily switch between conceptual projects in my daily work.

Please post back in the comments with answers to all of these so that I don't resort to editing C# code in Eclipse. Thanks.

Thursday, November 11, 2010

Testing declarative Eclipse expressions

Our Eclipse-based product plugs into the platform debug support. And we have a large number of launch shortcuts which have enablement expressions specified in plugin.xml. And they are a huge pain in the ass to test manually. If a particular shortcut is disabled when it should be enabled, there isn't a good way (that I've seen) to trace the evaluation of the enablement expression at runtime. So it comes down to stepping through the deeply nested Expression.evaluate(..) calls, and you can easily get lost.

This is one of those times where I feel like the light bulb should have gone on for me years ago. It turns out there is a much easier way to test these things: by writing JUnit Plug-in Tests for them.

What follows is some sample code to do this. Since I'm testing the enablement of launch shortcuts, the configuration elements are specific to that scenario, but you should be able to do this for any expression that appears in a bundle's plugin.xml.

In a @Before method, I read the expression from the plugin.xml and convert it into an Expression object.

IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(IDebugUIConstants.PLUGIN_ID, IDebugUIConstants.EXTENSION_POINT_LAUNCH_SHORTCUTS);
IConfigurationElement[] infos = extensionPoint.getConfigurationElements();
for (IConfigurationElement elem : infos) {
  String id = elem.getAttribute("id");
  IConfigurationElement contextLaunch = null;
  IConfigurationElement enablement = null;
  if ("myShortcutId".equals(id)) {
    contextLaunch = elem.getChildren("contextualLaunch")[0];
    enablement = contextLaunch.getChildren("enablement")[0];
    expression = ExpressionConverter.getDefault().perform(enablement);

And in a @Test method, I set up the context I'm trying to mimic and evaluate the expression.

public void ui() throws Exception {
  List<object> ctxt = new ArrayList<object>();
  ctxt.add(selectedObject /*Some IResource, perhaps*/);
  IEvaluationContext context = new EvaluationContext(null, ctxt);
  context.addVariable("selection", ctxt); //$NON-NLS-1$
  assertEquals(EvaluationResult.valueOf(m_uiEnabled),  expression.evaluate(context));

Now I can muck around in those delicately constructed XML expressions and rest assured that I have a test suite watching my back.

Monday, February 1, 2010

JUnit4 and the Eclipse Test Framework: Success!

(If you're eager, just jump down to the bolded part about victory.)

First, some background. I think the Eclipse Test Framework is one of the gems that is part of Eclipse. Effectively it's a way to run JUnit tests against your bundles while Equinox OSGi is running. You can also have the whole workbench UI running if you like, which I think is a common case. In fact, for quite some time, that was the *only* case that I considered it for. If I had a JUnit test that didn't need the workbench, I could "Run As -> Junit Test". If I had a Junit test that needed the workbench, I could "Run As -> Junit Plug-in Test". But I never really mentally equated the "workbench" with "OSGi framework."

Then I went to write a test for one of my bundles that has a dependency on Jetty. And its a version of Jetty that is different from the one that ships with Eclipse. When I ran it as a vanilla "Junit Test" from within Eclipse, everything worked fine. I think I just "got lucky" and it picked up the right version of Jetty when I launched the test. But when I ran my test via the Ant "junit" task (no Eclipse Test Framework), it failed because the wrong version of Jetty got loaded. All of a sudden I realized that without my delicately constructed dependencies being managed by OSGi, I was lost back in the world of "which JAR file is getting used?"

So, this brings me to the real guts of this blog post. After discovering I needed OSGi during test execution, I took a second look at the Eclipse Test Framework. Wow, this looks promising! Headless OSGi-based bundle testing! Just what I need. So I converted my build script to go that route, only to run smack dab into bug 153429, which captures that the Eclipse Test Framework only supports JUnit3.

That was at least a year ago, maybe two. I commented out my Jetty test and continued running my other JUnit4 tests using Ant. I even wrote some JUnit3 tests that I could run against the Eclipse Test Framework. Meanwhile, the CC list on bug 153429 continued to build and milestones kept passing without any progress. I stubbornly left alone my Jetty test, refusing to rewrite it for Junit3 since I figured Junit4 on ETF was right around the corner.

Finally with Eclipse 3.6M5 we have complete and utter victory. I have successfully executed my Junit4 tests with the Eclipse Test Framework. I'm not building my product against 3.6 yet (still 3.5.0 actually), but I still was able to grab the zip for ETF and make it part of my base Eclipse for PDE build to consume.

Now that I have my tests working, I do have some observations to share.

Rather than launching the SDK to run my tests, I'm launching my own product, spit out by PDE build. Part of the reason is that I have some additional plug-in tests written using WindowTester, and they care that it's my product which is launched, not the SDK.

There was a gotcha with this. ETF was created before p2. So you just dropped your test bundles into the "plugins" folder of the SDK, launched the SDK specifying the ETF application and test bundle / test class, and off you go. Today, if you do the same, and you're launching the SDK to run your tests, it will still work because the SDK ships with the dropins reconciler enabled. My product does not (which is the default, I believe). So I couldn't simply drop in my test bundles and make them available for ETF to find.

The solution to this is actually quite clean and works nicely.

  1. Enclose test bundles in a test feature, expressing the appropriate dependency on ETF. (Hint: I had to edit the feature.xml manually to include it, since I didn't make ETF part of my target, so I couldn't pick it from the PDE editors.)
  2. Run PDE build to build the test feature after building the product.
  3. Save off a copy of the product before I test with it.
  4. Formally install the test feature into the product using the p2 director.
  5. Launch the product, specifying the ETF application, and a test bundle / test class that has been installed into the product.

I've also included in my test feature the EMMA OSGi bundle for measuring the coverage provided by my bundle tests.

Thanks to everyone who voted, provided patches, and general community support to get the ETF supporting JUnit4. It really completes the testing package that is available to developers working with Eclipse and more generally OSGi.