Jump to: navigation, search

PDT Dev2Dev - Unit tests for CodeDataResolver and ContentAssistSupport

About a month ago I was honored to fix several bugs related to code links in the PHP Editor, which caused me to develop a light and simple way of testing CodeDataResolver class and yesterday I ported similar solution into test of ContentAssistSupport.

Getting Offset

The main problem in testing editor related issues is you should operate with offsets, which are not visually exposed. So I built a trivial utility Utils.getOffset() which translates the visual line and position for the specified document to the absolute offset. The utility's declaration is:

public class lib.org.eclipse.php.test.headless.core.Utils {
  public static int getOffset(int line, int offsetAtLine, IDocument testDocument) throws Exception;
}

It means you can put 2 numbers you see in bottom of your eclipse editor, decrement them by 1 and receive the offset in the document. The only incomfortability of working with the utility is that there is no way to work with hard tabs (\t).

Writing Tests

Since we have the utility, we can easily wrap it with the needed functionality, like:

public class org.eclipse.php.test.gui.ui.editor.contentassist.TestContentAssistSupport {
  private ICompletionProposal[] getProposals(int line, int position) throws Exception {
    IDocument document = viewer.getDocument();
    int offset = Utils.getOffset(line, position, document);
    viewer.setSelectedRange(offset, 0);
    return processor.computeCompletionProposals(viewer, offset);
  }
}

and

public class org.eclipse.php.test.headless.core.util.TestCodeDataResolver {
  private CodeData[] resolve(int line, int position) throws Exception {
    final int offset = Utils.getOffset(line, position, testDocument);
    return resolve(offset);
  }
}

Afterwards, you should just edit the tested .php file, see at which point do you want to get completion/link, write down the point location and create the tests, like:

13:// test method completion after literal  operator:
14:$var->doSomething() and $var->doSomething();
public void testMethodAfterLiteralOperator() throws Exception {
  ICompletionProposal[] computeCompletionProposals = getProposals(13, 30);
  Assert.assertEquals(1, computeCompletionProposals.length);
  Assert.assertTrue(computeCompletionProposals[0].getDisplayString().startsWith("doSomething()"));
}

or

46:// test this reference:
47:class Class6 {
48:    function function1() {
49:        $this->function1();
50:    }
public void testThisReference() throws Exception {
  final CodeData[] codeData = resolve(48, 12);
  Assert.assertEquals(1, codeData.length);
  Assert.assertTrue(codeData[0] instanceof PHPClassData);
  Assert.assertEquals("Class6", codeData[0].getName());
  final int modifiers = ((PHPClassData)codeData[0]).getModifiers();
  Assert.assertEquals(0, modifiers & PHPModifier.INTERFACE);
}

That's all folks. --Seva Lapsha 09:40, 21 October 2007 (EDT)