Why Should We Test Software?
Introduction
Recently, I’ve set higher expectations for my programming, and testing has become a crucial area.
But does a working program mean testing is unnecessary? When I first started working, I actually spent some time doing automated QA engineering, but back then, I didn’t really understand the reason for writing tests; I just automated testing because there was code, without thinking too much.
This article is aimed at those without testing experience who want to get started, targeting someone like my former self.
Why Test? How to Realize the Value of Testing?
Writing tests is a good thing, right? It can automatically verify the behavior of the program, ensuring its correctness, so you don’t have to test manually every time; automation can save manual testing.
This was my initial thought, and then I dove in and wrote a lot of tests, spending a lot of time adding tests for every feature, only to find… it didn’t really make much difference.
1. Tests Only Have Value When Executed
The value of a program is reflected when it is executed and used, and the value of a test is reflected in its verification of the correctness of a certain behavior of the program; even if the program’s architecture is poor, it can still produce value because it works. Similarly, a perfect test has no value if it doesn’t verify any behavior.
The biggest mistake I made was simply writing a lot of tests without actively executing them. Letting tests run and verifying the behavior of the program is where the value of testing lies. Successful tests give you confidence, while failing tests help you catch bugs.
Here, confidence refers to being sure that the program behaves as expected, which gives you more confidence to structure the code and ensure that changes won’t affect the verified behaviors. The importance of integrating testing into the development process is as significant as testing itself; tests that don’t run are merely case documents. Does anyone look at infrequently used and non-binding specification documents? No!
2. Tests Are Documentation
As mentioned earlier, tests are like specification documents. Imagine a detailed specification document that, through some magic, can automatically verify the behavior of the program anytime and anywhere, reminding developers where things don’t meet expectations… isn’t that testing?
Testing is essentially a form of automated specification. Development and testing are not two separate worlds but rather a complementary relationship. By repeatedly writing down expectations for the program in advance and practicing them, you discover TDD (Test Driven Design)! This approach prevents tests from becoming disconnected from specifications because tests are specifications.
However, here, engineers write down their expectations and iteratively produce programs that can be automatically verified for correctness. Business people also have their own specifications to write, integrating everyone’s documents into a specification based on behavior rather than implementation details, and adding tests and implementation details based on evolution; this is BDD (Behavior Driven Design).
The meaning of “tests are documentation” is to encourage a shift in thinking about testing, not to see it as a burden, but to understand that in development, the implementation is the “result,” but the “reason” before that is equally important.
3. Writing Tests for Greater Efficiency
Saving Time: Some types of problems take a lot of time and effort to test, possibly requiring specialized simulations of users performing specific operations or permissions, waiting for screens to load, verifying screen elements, and validating various states… which require a lot of manual time or are difficult to achieve manually. In the end, automated testing is a worthwhile investment.
Reducing Risk: Sometimes, a program is so important that even a tiny error cannot be made (financial transactions, life-critical situations), so testing can help ensure the correctness of the program. In the end, slowing down development to ensure everything works correctly is also worthwhile.
Conclusion
Testing is a controversial topic. Flexibility or correctness—what do you choose? Is it better to have good specifications before implementation, or to implement first and then add specifications? This is a perpetual question. Some prefer to sacrifice static checks, while others believe that testing is necessary, strict, and takes precedence over practice. Behind this is not just a technical issue, but a matter of team culture and product considerations.
I can be sure of one thing: untested code is either very simple and needs rapid iteration (its value is unclear), or it has become spaghetti code that no one knows how it works (valuable but you fear making changes). Balancing these two points is also an art.
> Legacy code refers to valuable code that you are afraid to change.
## Further Reading
- [We Finally Agree On Unit Tests - Theo - t3․gg](https://www.youtube.com/watch?v=MbU-PKukdMw)