Tuesday 21 January 2014

Why I use integration/acceptance tests

I recently posted about my annoyances of setting up integration tests in a separate directory structure than normal unit tests when using the Maven dependency management system. I briefly posted how I resolved this problem, but did not mention why I was writing integration tests.

I am relatively new to Javascript development, having done some web development in PHP many moons ago (professionally I am a server-side developer, working in a team that utilises TDD, continuous integration, etc). I was finding that as I developed the client side functionality, I was constantly breaking existing functionality as I couldn't be bothered going through and clicking on every interactive part of every webpage to ensure that everything still worked. This was becoming a real annoyance, with refactoring of the client side code becoming more risky as I didn't have any tests to ensure that functionality remained unchanged.

Changes to my APIs defined by my Spring MVC Controllers were breaking the interaction between client and server without me even realising. I knew that the functionality on the client and server sides worked independently, but I was not testing their interaction. The same could be said of my database calls. I knew my individual components of the system were working as expected, but their interactions was not!

All of this was enough for me to start writing integration (acceptance tests). To do this I used selenium for testing the interaction on the actual website (UI tests), and wrote an API so that I could interact with the server side. The API part of the testing actually allowed me to do two things:


  1. I was able to ensure that pure API calls worked correctly (with verification and validation not just happening via the web page as well!);
  2. I could set up the website environment using API calls when testing different parts of the UI using selenium (for every test I had to register a new user - I didn't want to test the user registration page in every test as this will make all my tests slower and adds more scope than is required to each test).


By writing a testing language that wrapped my API and Selenium UI calls, I was then able to define my business requirements in my acceptance tests. I find this a fair better way of defining behaviour than comments as these can often become out of date without developers realising.

Integration tests in a separate folder structure from unit tests in Maven

I have recently been working on introducing integration/acceptance tests into a stand alone web application. It was around this time that I really started to regret using Maven as my dependency management tool. It had been fine until the point where I wanted to introduce integration tests (note: the concept of acceptance tests does not exist in Maven) into different folder structure than normal unit tests.

Maven instantly became very angry at me for wanting to do this, and insisted that if I wanted to do such a thing then I would want to do it in a separate module as they shouldn't be written specific to one module. This makes sense if you have a multi-module project as these tests should be about end-to-end testing. However, many projects are not going to be multi-module, and creating a separate module just for integration testing feels like I am over-engineering. What I wanted to do is simple against the Maven model.

After some serious faffing (and adding several new dependencies) I was able to get a solution where I my tests run in the "integration" phase of Maven, allowing for starting and stopping of Jetty in the pre-integration and post-integration phases.

pom.xml


This allows me to have the following project structure.

/src/test/java/
/src/integration/java/
/src/main/java/

I really wanted to avoid using a separate plugin for integration tests but could not get any other solution to work. I hope this helps.