Why should you write code to automate testing your application code?
Writing code to automate testing for the code of your application is often considered standard practice for more established tech organizations and is not usually considered for pet projects. As most developers rightly complain, writing tests can usually feel like a chore and wasted time when that time could be spent building the tool or product you need to ship. This is usually the case until it becomes harder as the project grows to add new features because you no longer remember the internals of how your code works and you are not very confident if you have broken functionality by adding new code. Relying solely on manual testing your code becomes inefficient quickly. It would often get ignored further down the line into the project except for say there are Quality Assurance (QA) engineers dedicated to this.
Tests usually become a topic for projects, especially if they were not considered initially and the project starts to grow. Understanding the necessity of tests earlier can help place priority on writing them and also in many cases convincing the product management that time should also be allocated towards writing tests when scoping out a new feature. There are still a lot of exceptions though when writing tests might not be necessary, in the case of Proof of Concepts (POCs) and experiments but based on my experience, the points listed below are just a few amongst many benefits gained from robustly testing applications in past and present teams I have worked in. Note that these points are not specific to any of the levels of the Testing pyramid or a Testing strategy, but the overall benefits I have identified.
Addressing edge cases
Thinking about edge cases and handling them during the implementation phase could be quite difficult as trying to mentally keep track of and address different scenarios your code could run against. Writing tests can help expose bugs in your implementation as you might be surprised how your code can start failing the moment you run it against a test that expects your code a certain way. In the case of Test Driven Development (TDD), you can spend time already thinking of all the different cases your code to consider before you even begin the implementation of your code, hence you can simply address all of the scenarios you have identified in your tests.
Test Driven Development (TDD) is a software development practice that focuses on creating unit test cases before writing the actual implementation code.
Easing the process of migrations and refactors
One of the worries of migrations to a new stack, paradigm, or library and also refactors, especially large ones is ensuring your code still works the same way after in terms of the business logic, if that was one of the end goals of the effort. It is very easy to break things with these kinds of efforts and to manually ensure that things stay the same can sometimes be impossible to do. Having tests that you can run your changes against periodically can help spot bugs you might have introduced. This is particularly helpful especially if your tests are written to validate the results of your implementation rather than implementation details e.g this would be helpful for web integration tests that validate the result of a collection of components, rather than a unit test that might be checking if an instantiated class has the right attributes.
Increase confidence in adding new features
Adding new features to a project most times could seem like you would not be breaking existing functionality. Sometimes it might be very obvious how you might be changing how some existing logic works so it makes sense to test that the functionality is not broken, but sometimes it could be very unclear how you might affect other parts of the code and it might seem that there is no dependency. Most code bases are not perfect as there would always be some part of the code that might not be very obvious to understand and might not even have documentation. Having tests to run your code against can help protect these areas and ensure that they always work as expected.
Reducing the need for manual QA effort
Writing code to automate the testing of your application can help reduce the need for manual testing by QA engineers or even software engineers over time. This could reduce the need for manual QA for ideally only new cases and cases that have been tested before could be automatically tested whenever new changes are made.
Depending on the Testing strategy you adopt and the layers of the Testing pyramid that you can build, the benefits of having tests for your code could be experienced to different degrees. There are also a lot of other benefits that I may not have mentioned, but the ones I have mentioned are the most obvious benefits I have experienced so far being a software engineer.