Testing your Software Architecture

Architectural Unit Testing

Architectural ‘Unit’ Tests are automated tests that focus on enforcing:

  • Static coupling/dependencies between the different elements of your program, such as functions, types, packages, modules, components, libraries and frameworks. You can test things like cyclic dependencies, dependence on third-parties, proper use of anti-corruption layers, etc.
  • Architectural style. Your team might have agreed on some layered architect, maybe you’re using the ports and adapters.
  • Cross-cutting concerns. You might want to enforce that ‘Services’ within your codebase are properly annotated with @Secured or that all the public methods in Services log at least once.

Example Tests

A Java Layered Architecture

ArchUnit is one of the first tools we’ll look at. This is a test to verify the structure of your typical N-Tiered/Layered architecture.

All .NET Core Services should be authorized

This test is written with the library ArchUnitNET, a port of ArchUnit for Java. It validates that all services have the attribute Authorize. Notice how you can compose bigger elements, such as ‘Services’, from smaller elements.

TypeScript business logic should not depend on the frontend

This example uses ts-arch to validate that they’re no dependencies on the UI from the business logic folder.

All .NET Core public methods must be tested (Custom Condition)

Most of the aforementioned tools also support extension. In this example, I used ‘custom conditions’ to make

Other Architectural Testing Techniques

Software Architecture does not only concern itself with simple maintainability rules, it’s much bigger than that. You typically design your architecture with select architectural drivers in mind, such as those listed in ISO 25010. They’re the ‘-ilities’ of your system and usually form the bulk of your architectural complexities, unless simplicity is your driving requirement 😉.

  • Using software package metrics to gather objective data about your codebase, then enforcing rules in some build pipeline. (Maintainability)
  • Employing Chaos Engineering tactics to validate your architecture at run time. (Reliability/Compatibility)
  • Automated penetration testing on all your microservices. (Security)
  • Using Lighthouse to detect problems with your web frontend. (Usability)
  • Performing automated load/stress/performance tests with k6 or JMeter. (Performance/Reliability)
  • Etc... You can enforce many architectural requirements by making use of fitness functions.

Conclusion

In this article, I’ve introduced you to the concept of Architectural Unit Testing. It's a tactic that focuses on enforcing certain architectural requirements on a codebase. We’ve looked at examples in the languages Java, C# and TypeScript. We’ve also briefly went over fitness functions, from the book Building Evolutionary Architectures.

Connect with me ❤

I’m usually down for a spar session. Maybe even a new code homie?

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store