Sunday, February 7, 2016

Developing an Integration Test Framework - Case Study


In the last two posts I described a test strategy and unit tests for a controller written mostly in java. The Master Controller interfaces with an http server hosting the View and a Model/Model Controller written in C. This Model/Model Controller was developed by a different software group and is like a black box for our purposes. I wanted the capability to test both our C/JNI layer and also test drops of the Model/Model Controller from the other software team. Integration tests provided me with the capability to accomplish both these goals, while also testing interactions between the modules unit-tested in isolation. I could test these interactions from the Master Controller with java test frameworks by observing expected system responses to stimuli, removing the need for an entirely separate C-based test framework. 

The Master Controller code splits its core functionality between "managers" with specific responsibilities, 
including handling boundary crossings to the View and to the Model/Model Controller. Each manager is housed in a container class. This is an excellent spot to introduce dependency injection for test components, as shown in the ManagerControllerSample.java below: 

I created a test framework that allowed for each integration test to determine for each manager whether it would be implemented as a mock, using the standard implementation, or using a spied version of the standard implementation. With Dagger2, I was able to inject the appropriate component (test or production) at run-time. In Graph.java we see the dagger graph. IntegrationTestBase.java  specifies the list of managers to mock and spy as seen in the call to initGraph(), and ManagerTestDataModule injects the appropriate manager type (standard, mock, or spy):


In the next post I will discuss an integration test that used this framework and a technique for synchronizing callbacks spanning thread boundaries.