Unit testing in Confluence plugins is something that has been bothering me for some time. I have been using pure unit tests (with some mocks) to enable me to get tests in, which has left me rather unsatisfied. A few days ago I came across this article Integration Testing of Confluence Plugins . It led me to creating a guide to testing a confluence Action which includes using a vm to render the output.
Setting up the POM.xml
<parent> <groupId>com.atlassian.confluence.plugin.base</groupId> <artifactId>confluence-plugin-base</artifactId> <version>22</version> </parent>
I am using version 22. For the latest versions see maven repository
This gets the ball rolling. It pulls down a few extras which enable:
mvn clean integration-test
to work.
Next you need to configure a few properties.
<properties>
<atlassian.plugin.key>com.adaptavist.confluence.yourPluginKey</atlassian.plugin.key>
<confluence.version>2.10</confluence.version>
<atlassian.product.data.version>2.10</atlassian.product.data.version>
<atlassian.product.test-lib.version>2.1.1</atlassian.product.test-lib.version>
<atlassian.plugin.application.version.min>2.10</atlassian.plugin.application.version.min>
<atlassian.plugin.application.version.max>2.10</atlassian.plugin.application.version.max>
<confluence.plugin.bundled>true</confluence.plugin.bundled>
<confluence.plugin.install>true</confluence.plugin.install>
</properties>
I have thus fair failed to find detailed and upto date documentation. So other than the information about the properties listed in Integration Testing of Confluence Plugins regarding what the properties do, I don't really know! I found that to be quite frustrating.
Writing a test
package it.com.adaptavist.confluence.myPlugin; import net.sourceforge.jwebunit.exception.TestingEngineResponseException; public class TestsIntegration extends AbstractConfluencePluginWebTestCase { public void testMyAction() { try{ gotoPage("/plugins/macroDesigner/MyAction.action"); }catch(TestingEngineResponseException e){ assertEquals("" , e.getHttpStatusCode() + " " + e.getMessage()); } assertTrue( getPageSource().contains("<strong>The output from my action<strong>")); } }
This is the basis for a unit test I have been using. You may note that gotoPage() throws a runtime TestingEngineResponseException, which to be frank is very evil. The tests take a few minutes to run, so when the fail its very important you have the information required to fix the test. When you are presented with a gotoPage() problem you simply get a stack trace telling you which exception you got, I switched this for the assertEquals in order to at least get the Http Status Code.
I also spend a considerable amount of time fixing a test which was bombing out out gotoPage() as a result of a VM file I had failed to submit to subversion (school boy error I know). Does show the value of these tests as missing VM files don't break the build and can very easily go unnoticed until after deployment!
So here are some tips.
| error code | reason | Possible fix |
|---|---|---|
| 404 | dead link | Check you have the URL correct |
| 500 | internal server error | Your plug-in is throwing an exception, make sure all your files including the VM files are uploaded. Also try your action manually agains't a version of confluence to ensure thats not giving the same issue. |
The 500 errors are a real problem as they take so long to solve based on the test output. Its a good idea to look at the confluence/output.log. You can set this up as an artifact in bamboo by setting
| Artifact Label | Artifact Copy Pattern | Source Directory |
|---|---|---|
| confluence logs | confluence/*.log | target |
| surefire-reports | surefire-reports/. | target |
| plugin | *.jar | target |
Notice I also added the surefire-reports which show the actual test results and the plug-in file so you can upload it to a running instance of confluence and test manually.
Conclusions
This testing framework is excellent. It actually runs your plug-in against confluence.
It does take quite a while to run up, a few minutes to run simple unit tests is defiantly a problem. It makes sense to have a continuous integration server, in my case bamboo run these test in the background and to use conventional unit tests to ensure all logic that can be tested is tested.
There is a lack of documentation to inform you about the various helpers and all the properties and version information. It could be that I have missed this, I didn't even find information relating to what has changed between versions.
I highly recommend this testing framework to anyone who is also using something like bamboo. Despite a few annoyances it does tackle a very real unit testing problem quite well. I will be continuing to experiment with this. So expect a tutorial on unit testing a macro next.


Comments (1)
Aug 17, 2009
James McGivern says:
Nice one, thanks this will be very useful!Nice one, thanks this will be very useful!