Steve Freeman on Ports and Adapters in System Testing


Growing Object-Oriented SoftwareRecently, we were fortunate to be joined by Steve Freeman (@sf105), co-author of Growing Object-Oriented Software, Guided by Tests, and one of the early practitioners of Test-Driven Development (TDD). Steve facilitated a discussion at our weekly dev session (aka Burrito Club) on how tests can and should be used to help shape the growth and evolution of software, particularly the use of Ports and Adapters to make testability a first-class concern.

Steve Freeman at thetrainline.com

Steve Freeman at thetrainline.com

We discussed quite a range of test-related topics, including:

  • Test maintenance
    • Intent
    • Lifecycle
    • Fragility
  • Test value:
    • Overhead
    • Granularity
    • Usefulness
  • TDD vs Design Up Front
  • What to test
  • How to test external dependencies (file systems, queues, etc.)

The last point was discussed at some length, and a really useful concept for system testing shared by Steve was that of Ports and Adapters (see Chapters 5 and 6 of GOOS), by which  testing and testability in particular are treated as first-class citizens of the development process.

When testing our software with external systems or endpoints which we cannot change, Steve recommended that instead of using Mocks to replace the external services during testing, which can be time-consuming and difficult to maintain, you should instead use ports and adapters, which work to insulate the domain model from the implementation details of the external services/systems.

When developing software in the GOOS TDD style we want to start with the system inputs and outputs and work towards the domain model (this is different from the DDD approach, which starts from the domain model). For example, in a simple web-based system, we might have inputs from Web Services and the UI, and outputs to Persistence, Reports, Web Services and the UI (the input and output categories will likely be slightly different for each system):

Inputs and Outputs

Inputs and Outputs

Next, we add the domain model, which we can treat this as a system in its own right:

Domain Model

Domain Model

Inputs and Outputs with Domain Model

Inputs and Outputs with Domain Model

In order to insulate the core domain logic from the technical implementations, add adapters (shown here in blue) between the domain model and the technical implementations:

Inputs and Outputs with Domain Model and Adapters

Inputs and Outputs with Domain Model and Adapters

Finally, we add Ports to connect the Adapters to the technical implementations which provide the real service (black arrows at the outer edges):

Full Diagram with Ports and Adapters

Full Diagram with Ports and Adapters

Nat Pryce (co-author of GOOS) explains here why the Ports and Adapters scheme is such a useful approach for system testing (basically, it becomes much easier to test endpoints which are not under our control).

Non-trivial web-based systems, such as those which power thetrainline.com and our other websites, rely on a large number of external services and systems for things like payment, reservations, and fulfillment. The Ports and Adapters approach covered by GOOS is one way of reducing the testing complexity and increasing the test coverage of such software systems.

(Thanks to Matt R for input, and Steve Freeman for feedback and for an excellent tech session!)

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