Saturday, May 9, 2009

Unit Testing plugin.xml Files

In eclipse, the plugin.xml file is used to help setup the extension points used by your plugins. However, the requirements for this are not unit tested for regressions or to make sure that it is even setup correctly to begin with. Plugin.xml files can be unit tested the same way as Java methods and classes can be tested. Why would you want to do this?Verify that internationalization requirements have been met.Verify that appropriate Id values are being set.Verify that the plugin exentsion point has been defined and hasn't accidently been moved.Verify the integrity of your plugin.xml files.Now there are multiple ways to do this, and I hear people cringing and getting ready to throw bottles at me for suggesting this. However, this can be done fairly easily and quickly without having to walk a DOM tree manually. In fact, with a little bit of XPath, one can quickly determine if the values one is expecting exist in the plugin.xml. So without further ado here is a sample of how to test that a org.eclipse.ui.menus toolbar extension is implemented as expected.Setup:@Overrideprotected void setUp() throws Exception { super.setUp(); loadPluginXML(); initXPath();} @Overrideprotected void tearDown() throws Exception { super.tearDown(); pluginDoc = null; xpath = null;}private void initXPath() { XPathFactory xpathFactory = XPathFactory.newInstance(); xpath = xpathFactory.newXPath();}private void loadPluginXML() throws Exception { File srcFile = getTestFile("/" + PLUGIN_XML); DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder domBuilder = domFactory.newDocumentBuilder(); pluginDoc = domBuilder.parse(srcFile);} protected URL getInstallLocation() { URL installLocation = XSLUIPlugin.getDefault().getBundle().getEntry("/"); URL resolvedLocation = null; try { resolvedLocation = FileLocator.resolve(installLocation); } catch (IOException e) { throw new Error(e); } return resolvedLocation;}protected File getTestFile(String filepath) { URL installURL = getInstallLocation(); String path = installURL.getPath(); String location = path + filepath; File result = new File(location); return result;}Basically, the code above will load the plugin.xml file from the plugin to be tested. In this case, it happens to be the org.eclipse.wst.xsl.ui plugin.xml that is to be tested. It loads it into a w3c DOM Document, and also creates an XPath xpath parser/compiler to be used by the tests themselves.Testing the plugin.xml Requirements:The main work horse that keeps one from having to walk the DOM tree manually to find the items to test is XPath. XPath is a very simple, but powerful query language for locating nodes or a set of nodes in a DOM document. Leveraging XPath we can setup queries to test the requirements of a plugin.xml file as follows:public void testDTDToolTipExists() throws Exception { String xpathString = "//menuContribution[@locationURI = " + "'toolbar:org.eclipse.ui.main.toolbar?after=additions']/toolbar/command[@id = " + "'org.eclipse.wst.xsl.ui.newDTDFile']"; XPathExpression xpathExpr = xpath.compile(xpathString); Element element = (Element) xpathExpr.evaluate(pluginDoc.getDocumentElement(), XPathConstants.NODE); String toolTip = element.getAttribute("tooltip"); assertEquals("Unexpected value for DTD tooltip", "%commandTooltipNewDTDFile", toolTip);}This specifies to find all menuContribution elements that have a locationURI attribute equal to toolbar:org.eclipse.ui.main.toolbar?after=additions. Then get the toolbar element. Then the command element that contains an id attribute equal to org.eclipse.wst.xsl.ui.newDTDFile.This element when evaluated should return the element that matches that expression. If it can't find it, it returns NULL. If the element is not null, then it retrieves from the located command element the toolTip attribute's value. This is finally compared to see if it contains the value expected.I use something similar in the development of the STAR standards but use XPath expressions to evaluate XML Schemas to make sure they meet the specification requirements for the standards we develop. One could also use Schematron to evaluate the requirements, but by using Junit it interfaces nicely with existing eclipse plugin unit tests.The above unit test, is for bug 271784.

No comments:

Post a Comment