Monday, August 25, 2014

JSR286 portlet unit testing with Jetty, Pluto and JWebUnit

Background

Unit testing using JUnit has been around for quite some time, and even though I have used in early JUnit versions, it got really going when I also started to use maven. It was quite easy to create unit tests for any of my classes. Since I worked a lot with portlets I wanted to do expand my unit tests to include portlets.

The JSR286 portlet standard has been around for a while and it surprised me that I couldn't find any unit tests for JSR286 portlets, only JSR168 portlets. The most helpful blog I found was this one Testing Portlets with Jetty, Pluto and JWebUnit but again it applies to JSR168 portlets. Starting from there I tried to do the same thing with JSR286 portlets, but the pluto version used wasn't designed to work with JSR286 portlet. However, it gave me a starting point to recreate the setup for JSR286 portlet unit testing.

Setup

I will be using only a minimalistic portlet to demonstrate the setup. My starting point is a minimalistic portlet set up with maven. I demonstrated how to set that up in my last blog entry. From there I enhanced it a bit to allow for more testing. Here is the portlet class, the portlet.xml and the jsp I am using.

Maven dependencies

Next I set up the maven configuration. For this example I am using a simple pom.

I will describe what all of this does starting at the top. It starts with the basic maven configuration for the project. Moving on to the build section. There are some issues with loading classpaths and if I don't tell the surefire plugin to not use the system classloader, jetty will not be able to find the JSTL tag library and thus the entire test will fail.

 In the dependencies section I will start with the standard portlet api. This is required to compile the portlet class. Next is the jetty-maven-plugin. This is the lightweight web container used as a web server if you will when we are running the tests. This is then used together with the maven-jetty-pluto-embedded plugin. Pluto provides the portlet engine for the portlet  and maven-jetty-pluto-embedded provides the possibility to use pluto together with jetty. Starting with version 2.0 of this plugin the JSR286 portlet specification was supported. Next is jwebunit-htmlunit-plugin. This is what I use for the actual tests in my test class. The exclusion in the dependency is for us to be using my own custom logging configuration and so is slf4j-log4j12. Also note that all of these dependencies (except for the portlet api) are using the test scope. This is because I will only require these during the test phase.

Also as a sidenote. Some of these implementations have newer versions available in particular the jetty-maven-plugin, but since one of the critical components is maven-jetty-pluto-embedded, the version I use here is the latest compatible version I have found I can use.

The test class

Now off to the test class. Basically I do this in three steps. Setting up the server, running my tests and shutting down the server.
The startup of the server can be done also through configuration, but I extended my work starting from the blog where I found the JSR168 examples so I will continue the same way. In the setUp() method I do all of the server configuration and startup work. The exact name of the method id not important, but it must use the @Before annotation. The first line defines the portlets I use in my tests, the exact name is not important but it must match the portlet name in the portlet.xml. There can be multiple portlets as long as they are on a comma-separated list. The server is created with only a port where the server is started. The port can pretty much be any port as long as it is not already in use.

Next the web application context is set up. Here I define a servlet url mapping and add pluto descriptors and classes in order to get a proper portlet engine. The web application context is added to the server and the server is started. Finally the base url to use for all tests is defined.

The tearDown method is run after all the tests have completed (using the @After annotation). All this method does is to stop the server.

Finally I have the test method. This is just a simple demonstration to get started. What you want to do with your tests is up to you. Any test method can contain a number of different tests and there can be multiple tests in a test class. Here I start navigating to the pluto portals front page, making sure a certain text and div is present.

Reduce logging

If you run the test with only the above setup, you will find there is some extensive logging done. This is because the logging is set to debug level. I find this a bit too talky myself. In order to fix this, first we must exclude the default logging from JWebUnit. Jetty uses slf4j and all I did from there was to add the log4j impementation of slf4j using this configuration.
This configuration will set the logging to warn level. This will reduce the logging drastically but the cause will still be logged if an error fails. You may need to adjust the log level for further debugging if a test fails, but I found this to be a nice setting. I have also added a configuration which will output maven-like logging.

References

Friday, August 15, 2014

Make your portlet development use maven in no-time

Background

I started using maven some time back and I have found many advantages. One in particular was the ease to run unit tests. This made me want to be able to unit test portlets. The portlets I create nowadays are all based on the JSR286 standard. I did not find any examples of that, but with some help from what I found I was able to do unit testing. First things first though. Before we can use unit testing for portlets, we need to have a portlet where we also use maven. This blog entry will show you have you as simple as possible get your portlet sources mavenized. 

I will not cover the topic of why you should use portlets or maven. There are so many good resources out there already and a simple search should be easy enough to find them.

Basic portlet

First of all I have a really minimalistic portlet. There is only what I need to have inb order for the portlet to work. The point was to give a basic example of what you need to do to start using maven to build your portlet. In this I had the portlet class, a jsp file, the portlet.xml, the web.xml and some resource bundle property files.

Preparations

In order to use maven you need to have some software installed. You need to have a jdk (I used the latest available from Oracle) and maven. Make sure you have your maven binaries set in your path and your JAVA_HOME environment variable set to the directory where you installed the JDK. Note! It must be the jdk, a jre will not be sufficient in the long run.

If you just want to use the central maven repository and have direct access to Internet you don't need to do any other configuration, but if your network setup is different you may need to look at additional steps to configure maven, such as using a proxy with maven.

Moving files

Maven use a standard layout for its directories. You are in no way obliged to follow this standard and I am not going to even get into a discussion about what is best, I will simply leave that up to you. In this example though, I am using the standard directory layout as it makes the maven configuration easier. 

A portlet is packed in a web application archive, a war file. While maven has no direct portlet packaging available, it is not really required either as we use the war packaging, which effectively does the job. With this in mind there in particular three directories which we will use from the maven standard.
At this step you should move all of your portlet files into these three directories.
src/main/java should contain all your java sources. It is the root directory of your java sources so if you have your classes in packages, that structure must still be intact. The compiled classes will end up in your WEB-INF/classes directory. src/main/resources contains non-java files which should end up together with your compiled classes. In this case the portlet ResourceBundle property files will be here. Again, if you are using a package structure for your resources, that structure must be intact. The resources files will be copied as is (depending on your maven configuration) to your WEB-INF/classes directory. Finally the src/main/webapp directory contains all the files which should end up in the root directory of your web application. This includes any jsps you may have as well as your META-INF and WEB-INF directories (and all the files there in such as WEB-INF/portlet.xml and WEB-INF/web.xml). 

After all of this is completed I ended up with the following file structure:

Maven configuration

The heart of maven configuration is the pom. It is in xml format and its name is pom.xml. This file was created in the root directory. First there was the basic stuff. I won't go into details of any of this. Some of it is fairly self explanatory, but for the rest I suggest you look at the pom reference.
Finally the portlet apis need to be added in order for the portlet class to be compiled. For this we add a dependency. A dependency is really what the name implies. In order to compile and build our portlet we have a dependency on another library (apart from standard java) in this case the portlet api. For this portlet to work only the portlet api is needed, but there may be many dependencies. Note the scope in this dependency. With the scope of provided we are telling maven that this dependency will be provided later on, we only need to use it now at compile time. This is true because the portlet libraries are provided by the portlet container when we run the portlet. The libraries should not be included in our war file.

Building

Now we are done and we are ready to build. The command to build, package and verify as much as possible without adding our built war to the local or remote repository is mvn verify. If all has been done right you should get a BUILD SUCCESSFUL message in the end.

References