Tuesday, October 27, 2015

Organizing Java Integration Tests

In this post, I'll be switching gears from discussing automated tests with Webdriver to discussing integration tests that are included as part of an application's back-end Java code. 

In my new Software Engineer in Test position, I have been writing integration tests to test every API call we have.  This means that I have dozens of test classes, and over a thousand possible individual tests.  Today I'm sharing with you the strategy I came up with for organizing the tests. 

I sorted out the tests into four test types: 

Resource Tests:  these are the "Happy Path" tests- the tests where you expect things to work correctly.  Examples include:  POST requests with valid parameters, GET requests where the correct object is returned,  PUT requests where the new parameters are valid , and DELETE requests where the correct object is deleted.

Security Tests:  this is where I put all the tests that should fail because the user is not logged in.  For every method that is tested in the Resource Tests, there should be a similar test where the method is called, but the user is not logged in.

Validation Tests:  this is where I put all the tests that should fail because a value being sent is invalid.  Examples include: sending an null value where a value is required, sending an empty value where a value is required, sending a value with invalid characters (such as letters in a numeric field), and sending a value with too many or too few characters.  It's important to include tests for both Create and Update requests. 

Conflict Tests:  this is where I put tests that should fail because the request has been incorrectly formed.  Examples include: 
any POST, GET, PUT, or DELETE request where the required id is null
any POST, GET, PUT, or DELETE request where the required id is non-existent
any POST request where an id of the object about to be created is included
any PUT request where the id in the request does not match the id of the existing object

I created a package for each of these test types.  Then for each domain object, I created four test classes: one for each package.  For example, our code has a domain object called Phone.  Here are the test classes I created:

PhoneResourceTest- verifies that it is possible to add, get, edit, and delete a phone number

PhoneSecurityTest- verifies that it is not possible to add, get, edit, or delete a phone number if the user is not logged in

PhoneValidationTest- verifies that the phone number being added or edited is in a valid format (ten digits, no letters, etc.)

PhoneConflictTest- verifies that it is not possible to add or edit a phone number if the id of the associated contact is missing or incorrect, that it is not possible to add a phone number if there is a phone number id in the request, that it is not possible to edit a phone number if the phone number id in the request does not match the id of the phone number being edited, etc.

I hope this post will help you think about how to best organize your own integration tests!