Tuesday, January 04, 2022

Reduce Complexity in Tests by Breaking Up the Scope

A lot of people are overwhelmed with the complexity of their automated tests. I think the root problem in many cases is the scope of their tests are too broad - they try to tackle business logic, database integration, UI navigation, etc, in just one test. 

The solution here (as with any class or method that has too broad a scope), is to break this up into multiple tests:

  • Business logic should be handled in unit tests on domain classes - no database, no deployment to an app server, runs completely in memory. 
  • Integration tests should focus on integration logic, particularly in multi-threaded scenarios. Avoid testing business logic here.
  • Mock tests on Controllers ( or "Services", you're not following DDD 😢  ) should only test if the right objects and methods are being called, not the underlying domain logic.
  • UI tests (e.g. Selenium) should check the general behaviour of the UI - elements are visible, pages are navigable, etc. Don't try to test domain or integration in the UI.

Even with unit tests on domain classes, some devs find complexity because they're always testing at the aggregate root, where one has to provide too many parameters to the methods under test. Test on the lower level classes instead, where you'll find fewer parameters and simpler outputs.

An exception to my advice is if your system is so critical that it merits a few end-to-end (E2E) tests. For example, maybe it's a financial trading system where certain errors can cause a loss of billions of dollars, or maybe it's an aircraft flight control system (e.g. Boeing 737 MAX). In that case, identify just the most critical scenarios of these systems, and just clench your teeth for the world of hurt needed to write, and maintain, these E2E tests. 

No comments:

Post a Comment