Continuous Enterprise Development: The JavaOne Session


Parents aren’t supposed to play favorites with their children, but there’s always that one kid you’re just really proud of, right?  Admit it.

In my case at JavaOne 2012, it’s my last session with Aslak: “Continuous Enterprise Development: Case Studies in Java EE Integration Testing”.  We hit the stage at the Parc55 again in Cyril Magnin II/III Wednesday, 3 October, at 11:30 Pacific, and the session info can be found here.  From the abstract:

This highly technical session examines solutions for easing the testing of some of the more complex use cases within Java EE. Each example is backed by a runnable test (publicly available to participants), and the presentation covers automated continuous development of:

• The Web user interface (via Selenium)
• Persistent data and JPA
• Transactional boundaries
• Cloud-based deployments
• RESTful endpoints
• More

It showcases various techniques outlined in the book Continuous Enterprise Development in Java, forthcoming from O’Reilly Media, and is delivered by the authors. Expect a lot of proof through open source demos. You’ll see the presenters exercise the features of any compliant Java EE 6 runtime, using the Arquillian platform.

My team’s been lucky enough to enjoy some very positive feedback from our sessions over the years, but one comment we sometimes receive is that the message can be a little “soft” as we’ve catered to attendees of all skill levels.  So it’ll be interesting to see how this hour plays out, as the slide content will be limited to some supporting theory and the real meat of the course will be spent examining some solutions to the rougher edges of Java EE development.

I always want to kick myself for putting “Testing” in the title of these things, because that implies something separate from “real” development.  In truth the opposite is more accurate.  I’m fond of saying that “Testing is Development”, but the sentiment is better expressed by Jeremy Norris:

The purpose of automated testing is to enable change. Verifying correctness is just a nice side effect.

…or Tim Ottinger:

Move testing from the caboose to the engine.

Dan Allen voices the soundbyte “Coding with Confidence”.  Whichever way you spin it, the point is to consider testing a first-class citizen within your code.  In fact, I place it in order of importance somewhere below API design but definitely above implementation bits.  It’s a decent testsuite that enables me to brazenly work on a month-long refactoring that results in a 4000-line patch to be committed and released together.  The API is your contract with calling client code;  the testsuite is the contract your implementation has with your API.

So today’s session is going to cover the testable development of roughly 5 use cases.  I say “roughly” because we’ll favor quality over quantity; we want the talk to be fairly interactive with observations and suggestions from the attendees, so if we have to punt on some of the examples in order to give more complete coverage to a a fewer number, so be it.

Working with Data

One of the questions we most often receive revolves around interacting with a database.  The point of an application is to do stuff to state, and most programs require persistent state in some form or another.  Today we’ll focus a bit on relational mechanisms via JPA.

The example we’ll pull from here is a work-in-progress for the Book, a standard N-tier application with a JSF frontend.  While we spend a lot of time talking about the importance of integration testing alongside a backing container, we shouldn’t forget the obvious utility obtained by exercising unit tests as well.  Bean Validation definitions on the entity model are a wonderful candidate for standalone bootstrapping thanks to Hibernate Validator, so we’ll ease into the talk with a quick analysis of this in action.  Also, Emmanuel is in town and we like to make him smile.

With the easy stuff out of the way, we move along to an integration test which uses the Arquillian Persistence Extension to prepopulate data before testing from an external model, returning the database to a configurable (row-level or table-level) state when done.  Additionally, we can configure the feature to use transactions under the hood to roll back all changes made by the test upon test completion.  Sidenote: one of my favorite things about this extension is that it’s lead by a community contributor, Bartosz.  A simple annotation on the test methods does the dirty work for us:

@UsingDataSet("test_objects.yml")

This simple YAML file defines our source data for use in testing.

The View Layer

On the other end of the spectrum, seeing our data returned in the expected format is more than a nice bonus.  Of course, parsing out the possibly huge output from an HTML page can be a bit of a drag, so we’ve got a few tools to help in this department.

We use the same example here as we did with data, this time centering on the ConferenceTestCase.  There’s a lot going on here.

Remember that white-box testing allows us to inspect the inside of a system, while black-box testing focuses on the outside view.  With the following annotations above the test class, we’d like to introduce “gray-box” testing:

@WarpTest
@RunAsClient

Arquillian Warp is an extension which allows a test to both initiate a client-side request and perform assertions on server-side logic from inside the container.

Arquillian Drone lets us simply control the lifecycle of Selenium, through which we’ll examine UI output via a real web browser.  With the addition of Arquillian Graphene, we’re given an object model view of the DOM like this:

@FindBy(id = "conference")
private ConferenceView conferenceView;

Using this mechanism we may actually “mock” the data model used to render the response without going to the database.

Likely this example on its own should go into its own blog post, and it’ll definitely be used in the book.  So we’ll let it mature a bit then document it fully. :)

Testing Close to the Production Environment

With the advent of Cloud it’s become quite easy and cheap for us to spin up instances that are nearly equal in their makeup.  Because we should aim to exercise our application in an environment as close as possible to Production, it’s nice to take advantage of this setup as either a remote personal server extension to our development environment, or as a shared staging server for the development team.  We’ll see three approaches to interacting with OpenShift.

  • Attach a debugger from your development machine to the remote instance, allowing inspection of running code and hotswap.
  • Trigger Jenkins builds from a repository push, and on successful build, push changes to the staging and/or production instances
  • Use the Arquillian OpenShift Container to execute locally-initiated client tests upon a remote instance in the cloud.

The demo we’ll use for this is located here.  Go ahead and put your personal mark into what will become our test data!

Transactions in Action

I’ve always liked showing how to leverage in-container testing to perform assertions on the configuration.  One of my favorite demos from the EJB 3.1 book shows how a simple omission of a transactional annotation can result in a serious change to your application and potential loss of revenue.  Transactional boundaries are important to respect, and they must be set appropriately.

Aslak has recently written another example which allows the test case to gain control over the UserTransaction in play:

@Inject
private UserTransaction transaction;

From there we get to play around with generic Callable instances, really to wrap any action in a Tx:

private  T transactional(Callable transactionalCallable) throws Exception {
  transaction.begin();
  T result = transactionalCallable.call();
  transaction.commit();
  return result;
}

Motto: Don’t be afraid to dig into the inner workings of the container while you’re in there.

Get some REST

To be honest, RESTful testing is one of the less-complex cases we get requests for.  It’s typically a black-box request from the client to a service, one illustrated by this example from the Arquillian Showcase.

The magic bit is knowing exactly what URL to hit, as the host or context path shouldn’t really be hardcoded.  Arquillian helps us out here:

@ArquillianResource
URL deploymentUrl;

…and from there it’s business as usual, though the RESTEasy Client APIs make this even simpler for us than a standard HTTP client:

ClientRequest request = new ClientRequest(deploymentUrl.toString() + RESOURCE_PREFIX + "/customer/1");
request.header("Accept", MediaType.APPLICATION_XML);

// we're expecting a String back
ClientResponse responseObj = request.get(String.class);

Assert.assertEquals(200, responseObj.getStatus());
System.out.println("GET /customer/1 HTTP/1.1\n\n" + responseObj.getEntity());

String response = responseObj.getEntity().replaceAll("<\\?xml.*\\?>", "").trim();
Assert.assertEquals("1Acme Corporation", response);

Wrap-up

Again, this presentation is more fun when it’s interactive.  There’s definitely more than one way to skin a cat, and we’re open to hearing your suggestions, solutions, and pain points.  It’s likely that some ideas you’ve got could make it into the book, so we’re excited to see and hear from you, either in person at the session or here in the comments.

S,

ALR

About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: