>Testing Content Assistance Proposals

>The topic of how testable or untestable eclipse code is came up on #eclipse-dev last night. There are cases where the code is very testable, but in the vast majority of cases it’s difficult to figure out how and where to setup the code to produce a test. One such place can be content assistance proposals. I’m going to take a look at how XSL Tools has implemented some tests for content assistance proposals using the Structured Source Editor framework from WTP. Taking the time to write tests even if it is just for a bug fix on a Null Pointer check is worth it. For one thing it does allow you to safely refactor your internal code, while maintaining the same functionality.

Let’s get started. The sample I’m going to show here is content assistance for other XML elements and attributes that aren’t in the XSL Namespace for an XPath Expression. In particular this will be looking for elements that are part of the XHTML namespace. The namespace prefix has been defined as xhtml. The grammar for the XHTML file is contributed using the XML Catalog extension point through the test plugin.



public void testProposalsIncludeXHTML() throws Exception {
fileName = "TestXPathXMLProposals.xsl";
String xslFilePath = projectName + File.separator + fileName;
loadFileForTesting(xslFilePath);

int offset = 251;

ICompletionProposal[] proposals = getProposals(offset);
assertNotNull("Did not find proposals.", proposals);

for (int i = 0; i < proposals.length; i++) {
if (proposals[i].getDisplayString().contains("xhtml:")) {
return;
}
}
fail("Did not find XHTML proposals.");
}

This the main part of the test. There is a helper method used to load the XSLT file for testing. Allowing different files to be tested. The other important option is setting the offset position within the document to retrieve proposals.

Next the helper method getProposals is passed the offset, and the proposals are returned.

If we had proposals, then we check for the xhtml prefix, if we don’t find the proposals we just fail the test.

Test setup:

One of the items that may need to occur is to setup a project in the testing workspace. Plus the test may need to have some resources copied over to the workspace so that it can load the appropriate files for testing when needed. The bulk of this work is abstracted out to a AbstractXSLUITest class, based off some code from the WTP xml tests.

To setup the project we override the setUp method:


protected void setUp() throws Exception {
super.setUp();
setupProject();
}

And we call the setupProject method.



protected String projectName = null;

protected void setupProject() {
projectName = "xsltestfiles";
IProjectDescription description = ResourcesPlugin.getWorkspace()
.newProjectDescription(projectName);

IProject project = ResourcesPlugin.getWorkspace().getRoot()
.getProject(projectName);
try {
project.create(description, new NullProgressMonitor());
project.open(new NullProgressMonitor());
} catch (CoreException e) {

}
}

This opens the project so that we can find the files we need later to test with.

Loading the File to test.

As was shown in the test, there is a common method used to load the files for testing. This will find the file in the workspace, and then load the source viewer and configure the viewer for testing.



protected IFile file = null;

protected void loadFileForTesting(String xslFilePath)
throws ResourceAlreadyExists, ResourceInUse, IOException,
CoreException {
file = ResourcesPlugin.getWorkspace().getRoot().getFile(
new Path(xslFilePath));
if (file != null && !file.exists()) {
Assert.fail("Unable to locate " + fileName + " stylesheet.");
}

loadXSLFile();

initializeSourceViewer();
}

protected void loadXSLFile() throws ResourceAlreadyExists, ResourceInUse,
IOException, CoreException {
IModelManager modelManager = StructuredModelManager.getModelManager();
IStructuredModel model = modelManager.getNewModelForEdit(file, true);
document = model.getStructuredDocument();
}

Source Viewer Configuration:

The test needs to have the source viewer configured correctly, so that content assistance can be enabled for the viewer we are testing against.



protected IStructuredDocument document = null;
protected StructuredTextViewer sourceViewer = null;

protected void initializeSourceViewer() {
// some test environments might not have a "real" display
if (Display.getCurrent() != null) {
Shell shell = null;
Composite parent = null;

if (PlatformUI.isWorkbenchRunning()) {
shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
.getShell();
} else {
shell = new Shell(Display.getCurrent());
}
parent = new Composite(shell, SWT.NONE);

// dummy viewer
sourceViewer = new StructuredTextViewer(parent, null, null, false,
SWT.NONE);
} else {
Assert.fail("Unable to run the test as a display must be available.");
}

configureSourceViewer();
}

protected void configureSourceViewer() {
sourceViewer.configure(new StructuredTextViewerConfigurationXSL());
sourceViewer.setDocument(document);
}

Retrieving the Proposals:

Now that the setup of the viewer is completed we can actually retrieve the proposals. The bulk of the work is done through a simple call to the actual XSLContentAssistProcessor class, and particularly the computeCompletionProposals method. (If testing XML proposals the class would be XMLContentAssistProcessor.)


private ICompletionProposal[] getProposals(int offset) throws Exception {
return new XSLContentAssistProcessor().computeCompletionProposals(sourceViewer, offset);
}

The sourceViewer that contains the document that was loaded, along with the offset. The results are the proposals that were returned at that particular position. Hopefully, this sample has shown a way that SSE based editors can test their content assistance proposals.

Advertisements
This entry was posted in eclipse, refactoring, testing. Bookmark the permalink.

One Response to >Testing Content Assistance Proposals

  1. AlBlue says:

    >These kind of blog posts are excellent, and open up a way to promote best practice in plugin development. I only wish I had spare time to help out with the XSL Tools effort – you’re doing a great job.

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