Development/GetInvolved/DeveloperStepByStep/javapython

Convert Java unit test to Python
see also: Development/Python_Unit_Tests

In order to simplify our unit test setup it was decided to convert all the Java-based unit tests to be Python-based. The workflow roughly is:


 * 1) Create a new python test
 * 2) Create new make file or extend already existing one
 * 3) Add new test to this Makefile
 * 4) Remove old Java unit test.

Check: https://gerrit.libreoffice.org/4294 and https://gerrit.libreoffice.org/6017 for inspiration.

Developers who want to learn about the UNO interface (the universal interface to LibreOffice) are recommended to submit a couple of patches.

There are a couple of pitfalls when converting, this page tries to provide some common help. For specific help please talk with us on or mail.

Where to find the unit tests
All our tests can be found in

This is an example of a succesful patch: gerrit patch

Corresponding makefiles
There are 2 makefiles you need to modify:


 * remember to remove reference to the java file
 * normally you need to add the new file in 2 places

Delete the Java file:

Add the Python file

Code translation hints
A few things are actually a lot easier to do with the Python unit tests than with the Java test framework, because:
 * Python is dynamically typed
 * Python tests are run in process instead of connecting from an outside process
 * the Python bindings are provide a deeper integration into the language that Java (they are "pythonic")

When translationg code that might lead to the wonders on "How to do this Java code in Python?", when the Java code is indeed superficial in Python -- there is no explicit code needed to do what the Java code does.

Dynamically typed (python) versus strongly typed (java) languages
You would _not_ need most of the following in dynamically typed languages like Python or StarBasic, only in statically typed languages like Java or C++.

A typical java construct: Generally in UNO you are communicating by calling function over references to interfaces, not references to services or implementations.

Björn made an excellent talk at a LibreOffice conference to this theme, please watch the first 5 minutes of conference video.

Lets take the other java example: The first line:

according the documentation at: doc

returns a new instance of a TextCursor service which can be used to travel in the given text context. So this gives you a reference to the  interface of a  service. Note that there is a difference between a service and an interface.
 * TextCursor interface
 * TextCursor service

However, from: XSimpleText

we know we need to give insertControlCharacter(..) a reference as first parameter, not a  reference, which is different. We know from the documentation of createTextCursor(..), that the reference holds a service and we can see from: TextCursor text that the com::sun::star::text::TextCursor service extends a com::sun::star::text::TextRange service: TextCursor text which implements a com::sun::star::text::XTextRange interface: textrange

This can be rather confusing, but try to take it step by step then it hopefully makes sense. There are a lot of UNO Documentation and it is not always easy to match head and tail.

So:

- we have a  reference to a   service

- we know that the  service also implements the   interface, that we need.

Thus (in Java) we need have a way to get a reference to a interface out of our reference to a, which we know holds a  and:

does that: xParaCrsrAsRange is now a reference to a com::sun::star::text::XTextRange interface of the com::sun::star::text::XTextCursor. Thus we can call insertControlCharacter(..) with that.

So how does that work in dynamically typed languages like StarBasic or Python? Well, there you just hold a reference, with no static typing attached to it. Thus you can use _any_ of the interfaces implemented by the service behind it without doing any confusing conversions. If you do:

in Java, you can _only_ use that as a XTextCursor without conversions. If you do:

in Python, you can use that as XTextCursor, XWordCursor, XSentenceCursor, XParagraphCursor, XPropertySet, XPropertyState, XMultiPropertyStates, XDocumentInsertable, XSortable. And thus for the Java code the equivalent in Python is simply:

because there is no need at all for conversion or even a xParaCrsrAsRange variable. So, in Python (or StarBasic) you never need to use queryInterface at all!

Out-of-process UNO (Java tests) vs. In-process UNO (Python tests)
There is often a lot of boilerplate code in Java tests to connect to LibreOffice and create a test document, e.g.:

in Python the equivalent is simply:

Pythonic syntax simplifcations
Since commit af8143bc it is possible to use native Python language features to write code that looks more natural. For example in most cases, there is no need to write: because a simple: does just as well. More lots of additional examples can be found in the commit message of af8143bc.

handle Sequence
Currently the python implementation only handles Sequence and not Sequence, therfore a rather clumpsy workaround need to used: