In the modern world of software development, any library or application of considerable size is incomplete and at significant long-term risk without a slew of automated tests. While unit and integration tests are used to ensure that all of the intricacies are covered in complex and stateful code, for the long-term health of your codebase, system testing should also be a crucial component of your test arsenal.
How Is System Testing Different?
The libraries and applications we develop are inevitably made up of many pieces. Unit tests are valuable for flushing out various corner cases in code, but the fact that they are focused on isolating a part of your codebase for conciseness and testability makes them less suitable for validating the health of the overall system.
System tests, on the other hand, attempt to stand up most, if not all, of the pieces of your application to test the way they integrate. In applications with some form of GUI, many of us have been in the situation where tests show that all of the processing of an event is okay, yet we still have a bug—and perhaps the very button to trigger the event wasn’t wired up properly!
Is It Really Worth the Time?
System testing does come at a cost. They also bring the cost of standing up all of the pieces of your monstrosity to the forefront. This gives you the chance to question the large-scale complexities of your system, and it may even drive some simplification to better tame the beast. Moreover, system tests are an excellent vehicle for acceptance tests to ensure that your application meets the needs of your end user—and continues to meet them as the system evolves.
Another excellent benefit that this level of testing provides is the ability to refactor the internal structure of your app without changing the system test, or at least its intent. Unit tests are very dependent on internal implementation details, and they require significant reshuffling when non-user-facing pieces change. By contrast, system tests allow you to maintain stability and sanity through major refactorings so that technical debt can be addressed to keep your codebase, and clients, happy.
Please Tell Me Things Are Getting Easier!
Many of us who have struggled with chasing Selenium, internally built against Firefox, have found that the movement to the WebDriver has created a great vehicle for a more solid/stable API. It’s also led to ChromeDriver, which provides a common API to test directly against the two most widely used browsers.
The birth of WebDriver/ChromeDriver signals a higher level of vendor devotion to testability and stability of their frameworks. In turn, this should drive longer-term stability of API, behavior, and most importantly, our own test suites as these browsers continue to evolve.