I am one of those developers who like to see how things work from inside. That's why I spend much more time with the source code, debugger and tracer rather than with javadocs or reference documentation.
When it comes to web applications I need an infrastructure that actually allows be to trace the running code. That is, start the web application, set the breakpoint, see get it triggered, see how and what is invoked. I want to be able to debug the web application just as I'd debug a desktop or a command-line app.
The problem with web applications is that they run on the server. This makes things more complicated since you need to setup this server, deploy your application - and somehow get your debugger working.
Over the past years I've tried numerous solutions for web app debugging - from remote debugging to special IDE plugins, but I wasn't really satisfied with any of this. It was always too much dependencies on the external server instance and IDE and too few control of what's happening.
Finally I have developed an approach which is based on the embeddable usage of Jetty. Jetty is a lightweight HTTP server and servlet container, which is very easy to embed in your own applications. By "embedding" I mean that you can create, configure and run a Jetty instance programmatically. For instance, from your unit or integration test.
The hifaces20-testing package provides a non-invasive infrastructure which allows you to start and run your web application in a servlet container directly from your test.
Core element of this infrastructure is the web application environment modelled by the WebAppEnvironment. Web application envrionnment is basically a servlet container (Jetty) which runs a single web application (your application). Basic usage is as follows:
Configuring, starting and stopping the server is actually a routine task, the code is almost the same. To avoid repetitions and keep it all as less invasive as possible, hifaces20-testing implements an approach which allows you to simply get an instance of web application environment injected into your test. There's two parts of this solution: indicating that you need an instance of WebAppEnvironment in your test and making use of the testing tools that actually create an instance of the web application environment, start it, pass it to your test and shut it down afterwards.
In order to indicate that you want an instance of WebAppEnvironment to be injected into your test, you can do one of the following:
- Annotate a public field of your test class with @PropertiesWebAppEnvironmentConfig
- Annotate a public setter of your test class with @PropertiesWebAppEnvironmentConfig
- Make your test implement the WebAppEnvironmentAware interface.
To make this annotation or interface work you need to actually employ the testing infrastructure hifaces20-testing offers. Depending on the testing framework you're using there are different ways of achieving that:
- With JUnit 3.8 and lower
- Extend the AbstractWebAppEnvironmentJUnit38Test class (it is already WebAppEnvironmentAware)
- With JUnit 4 and higher
- Extend the AbstractWebAppEnvironmentJUnit4Test class (it is already WebAppEnvironmentAware)
- Use the WebAppEnvironmentRule method rule
- With TestNG
- Extend the AbstractWebAppEnvironmentTestNGTest class (it is already WebAppEnvironmentAware)
- With Spring Test
- Use the WebAppEnvironmentTestExecutionListener
The @PropertiesWebAppEnvironmentConfig annotation actually specifies the location of the web.properties file which provides host, desired port, context path and home directory of the web application. Here's a sample file:
By default this file is searched under src/test/resources/web.properties, but you can specify a different location in the @PropertiesWebAppEnvironmentConfig annotation:
|Please note that specified port is the desired port. If this port is already occupied then testing infrastructure will search for a free port.|
Developing web applications involves a lot of live/hands-on testing. A quite frequent scenario is:
- check one thing or another;
Hifaces20 Testing supports this scenario by providing the AbstractRunWebApp abstract base class. Here's a usage example:
The RunMyApp is actually a pseudo-unit-test which can be started as such from the IDE (ex. in Eclipse: right click > Run As > JUnit Test).
- This pseudo-test starts the configured web application environment (your web application deployed in Jetty) and brings a small Swing dialog window.
- Now the server is started, you can open the browser and go to the target page (something like http://127.0.0.1:8080/MyApp - as configured in src/test/resources/web.properties) and work with/click through your application.
- Then you're done, simply close the Swing window, this will shut down the server.
- Configure the Highsource Maven repository in your pom.xml.
- Use the hifaces20-testing artifact in your builds:
- Download the distribution from here.
- Add highsource20-testing-version.jar to your classpath.
- You'll also need commons-lang, commons-io and slf4j-api (with the binding of your choice).