Written by Colin Skow
Testing is more than just testing. Despite its importance, many developers tend to shy away from writing automated tests, citing the added effort involved and the difficulty of quantifying its benefits in real-time. However, by shifting our perspective and emphasizing the value that effective test-writing and maintenance can provide, we can encourage developers to embrace this practice more readily. The purpose of this article is to share the different ways we can look at software testing that will effectively demonstrate its value to all stakeholders.
Looking at software testing
As business specifications. Automated tests serve not only as a means of verifying expected behavior, but also as a form of behavioral documentation. It is best when these tests are derived from business-readable Acceptance Criteria in BDD format (Given, When, Then) and closely tied to automatable tests using Cucumber. To obtain optimal insight into test coverage, these tests should be executed frequently via build pipelines (ideally on every code merge). By providing swift feedback on the application’s behavior, these tests serve as an early warning system for divergences between expectations and actual implementation, ultimately lowering the costs associated with issue discovery. They do not operate at a lower level and are implementation-agnostic, and are focused on happy path scenarios. Product owners and business analysts, who are domain experts, should take the lead in writing these tests, with support from quality engineers and developers. The sooner these tests are developed and automated, the higher the level of confidence in the application’s flow, and the better the test coverage at the UAT level.
As documentation. When developers write code, they do so with specific assumptions and intentions in mind. These intentions are documented through the tests they write, which serve as live documentation for the code under test. Unlike comments within the code that can easily become outdated, tests are constantly updated and cannot fall out of date, making them a reliable form of documentation. As tests fail during development, team members who have not worked on the original code gain a better understanding of the initial implementations. Additionally, these tests provide clear documentation for the intended usage of domain objects and utility functions, helping developers quickly learn the underlying app code. Quality engineers can also leverage tests within the source code to gain a better understanding of what needs to be tested at higher levels, as well as how to use APIs effectively. By viewing tests as a form of living documentation, developers and quality engineers can ensure that their code is comprehensively and accurately documented, resulting in more effective and efficient development practices.
As a mechanism to improve code design. Code complexity makes testing hard. Test Driven Development (TDD) can help avoid overly complex code by driving developers to design inherently testable, maintainable, readable, extendable, and well-organized code according to established design principles and best practices. By prioritizing testing during the development process, it becomes more difficult to write unstructured spaghetti code that can be difficult to maintain and understand. Instead, TDD encourages the production of well-written code that is easier to comprehend and navigate, making it faster and more efficient for new team members to come up to speed. Although it may require some additional effort and time investment upfront, the improved code quality resulting from TDD can lead to significant time savings in the long run, as the entire development project benefits from better code maintainability and readability. By adopting TDD as a core practice in software development, developers can help ensure that their code remains functional and accessible, supporting the long-term success of their projects.
As a mechanism to increase dev velocity. Automated tests play a critical role in increasing confidence and reducing fear when it comes to software development. They provide developers with the ability to try out new ideas and refactor existing code with the assurance that they can always fall back on existing tests. When implementing new functionality that interacts with existing code, tests offer a sense of security. Passing tests indicate that development can move forward confidently while failing tests offer fast feedback that allows for swift resolution of regressions even before committing changes. By effectively leveraging Test Driven Development, you can create a safety net that allows future development to progress seamlessly. While unit test coverage cannot guarantee the complete elimination of future bugs, it can limit their numbers. As new bugs are discovered, new tests should be created to ensure that they are caught as early as possible. By discovering and addressing issues early in the development lifecycle, you can minimize the impact on project velocity and prevent the costly delays associated with late-stage bug discovery.
As scientific experiments/defense. Proving the absence of bugs in a software system is an unattainable goal. In much the same way that scientific theories cannot be proved true, we can only test our software theories (such as functions, methods, and integrations) by subjecting them to numerous challenges involving variable combinations and global states to ensure their resilience. To increase our confidence in the software’s performance, it’s essential to conduct a diverse range of experiments that test both its functional and boundary aspects. Achieving this level of confidence requires a combination of creativity and rigorous testing, which should be applied to both manual exploratory testing and unit testing.
Automated tests are a crucial component of software development and must be held to the same quality engineering standards as any other code. The value of automated tests lies in their ability to provide a safety net for the code, but this can only be achieved if the team recognizes their importance and consistently utilizes them. Otherwise, they risk becoming an unnecessary abstraction that only hinders productivity. By prioritizing the creation and maintenance of high-quality automated tests, the team can ensure a more streamlined development process and deliver reliable software with greater efficiency.
In the intermediate run, you can have it all when it comes to the iron cross of software development: Fast(er than if you were to create a big ball of unmaintainable, extensible working mud), Cheap(er than the cost of maintaining a big ball of said mud), Good(which is built in assuming high quality testing and engineering efforts), Done(r than a big ball of mud that is falling apart). Testing code and software is not a primary reason for writing tests. By ensuring that quality testing and engineering efforts are built into the development process, testing code and software becomes an integral part of the project, and not just an afterthought. The benefits of implementing test automation solutions go beyond just testing code; it can also lead to faster development times and lower maintenance costs. It takes time and effort to create quality test automation solutions but to quote a fellow quality enthusiast, the juice is worth the squeeze.