I have explained in one of my last posts how to measure the coverage of the test of a Java OpenOffice.org extension. These white-box tests are generally not enough to ensure the quality of a development. XUnit tests are often used by developers to automate the tests. What about unit tests for an OpenOffice.org extension? Is there any way to automate the tests of a Java extension for OpenOffice.org? To improve the quality of the COOoder extension, I wanted to create some unit tests. I will present here some basic classes to use to create easy tests.
Theoretically...
Before presenting any code snippet, I need to explain the general principle of the unit tests for OpenOffice.org. The key concept of the following is that OpenOffice.org can be launched and controlled by a remote program. A JUnit test is a normal Java program and the idea is to make it bootstrap OOo, connect to it and execute the tests. Here is a small sequence diagram of what happens:
OpenOffice.org is bootstrapped once at the beginning by the test suite and stopped when all tests are run (this part has been forgotten on the diagram). The remote OpenOffice.org context is transmitted to all the test cases which can use it to set the fixture up, run the test and tear the fixture down.
...and practically
To implement all this nice feature, I have created some base classes for
the tests cases and suites. They both inherits from the JUnit
corresponding classes. The classes are in the
org.openoffice.coooder.test.base
package in the ooo-build project:
Bootstrap
: the OpenOffice.orgBootstrap
class modified to easily bootstrap the officeUnoTestSuite
: the test suite to use to run all the unit tests for OpenOffice.orgUnoTestCase
: the OpenOffice.org context-aware test case. This abstract class has to be the base of all the unit tests for OpenOffice.org Java extensions.
To correctly bootstrap the office, the program
folder of the
OpenOffice.org installation has to be added to theLD_LIBRARY_PATH
variable (PATH
on windows and DYLIB_LIBRARY_PATH
on MacOS). This
folder has to be passed as a property to the JUnit launcher using the
following JVM parameter:
-Dopenoffice.program.path=/usr/lib/openoffice/program
Now there is only to write the tests. Here is an example of test suite and a test case:
/**
* The test case class with two tests
*/
public class DummyTest extends UnoTestCase {
private XTextDocument mTestDoc;
public DummyTest() {
super();
}
public DummyTest(String pName) {
super(pName);
}
/**
* Fixture setup: creates an empty writer document
*/
protected void setUp() throws Exception {
mTestDoc = loadDocument("private:factory/swriter");
}
/**
* Fixture tear down: closes the document without saving
*/
protected void tearDown() throws Exception {
XCloseable xCloseable = (XCloseable)UnoRuntime.queryInterface(
XCloseable.class, mTestDoc);
xCloseable.close(true);
}
/**
* One correct test
*/
public void testHello() {
try {
String hello = "Hello world!";
mTestDoc.getText().setString(hello);
assertEquals(hello, mTestDoc.getText().getString());
} catch (Exception e) {
fail("Shouldn't have thrown an exception");
}
}
/**
* One failing test
*/
public void testFailure() {
fail("test will fail here");
}
private XTextDocument loadDocument(String pUrl) throws Exception {
XMultiComponentFactory xMngr = getContext().getServiceManager();
Object oDesktop = xMngr.createInstanceWithContext("com.sun.star.frame.Desktop", getContext());
XComponentLoader xLoader = (XComponentLoader)UnoRuntime.queryInterface(
XComponentLoader.class, oDesktop);
XComponent xDoc = xLoader.loadComponentFromURL(pUrl, "_default",
FrameSearchFlag.ALL, new PropertyValue[0]);
XTextDocument xTextDoc = (XTextDocument)UnoRuntime.queryInterface(XTextDocument.class, xDoc);
return xTextDoc;
}
}
/**
* The test suite class.
*/
public class AllTests {
public static Test suite() {
// The tests to run by the suite
Class[] testClasses = new Class[] {
DummyTest.class
};
// Create the test suite
UnoTestSuite suite = new UnoTestSuite(testClasses);
return suite;
}
}