Over the past week and a half I’ve been writing a Tic-Tac-Toe game in Python. Although I’ve written games like this in the past, I think I’ve finally learned why writing tests is so important. Here are my three main reasons why automated tests aren’t optional when it comes to writing production code.
Manual Testing Takes Time
Tic-Tac-Toe is a simple game with few moving pieces. At its core, all you need to do is draw the board, make your mark, check if the game is over and, if nobody won, do it over again as the other player. Pretty simple. But manually testing just these four systems became extremely time consuming and tedious within just a few days of working on the project.
Manual testing becomes even more daunting when you start adding features like save games or a scalable board. Keep in mind this is just Tic-Tac-Toe in the command line, no web browser interface, no REST API, just the command line. Just a few days in I have already reached a point where I have a choice to make. I could either start writing some automated tests, or manually test all my systems whenever I make a change. During this manual testing I will more than likely miss something crucial along the way. If this were a full scale, production application I would be in heaps of trouble if I had to test and debug my application manually (more on this later).
What this experience has taught me is that failing to write automated tests up front is going to have unforeseen consequences down the road. The amount of time I will end up having to spend to fully test my app manually will be far greater than if I had just written automated tests from the very beginning.
The Un-testables
There are some things that are tedious, extremely time-consuming, or down right impossible to test manually. Think about a method that is supposed to check if a Tic-Tac-Toe board of any size has a winning move on it. This could take a long time to manually test every possibility. You would have to load up your game multiple times and play games in many different configurations to make sure that your method was working properly. With a 5x5 Tic-Tac-Toe board you would have to do 12 different manual tests in order to test all the possible win conditions.
This doesn’t just apply to Tic-Tac-Toe either. A few months ago I wrote a command line Mastermind game in Ruby that needed to give a specific response back to the user based on what the user had entered and the code that the computer had stored. This situation is something that I would consider to be down right impossible to manually test. There are 1,296 possible different codes (in the base rules of Mastermind) that could be entered. You are able to pare down that number quite a bit but the amount of manual testing you would have to regardless, to ensure your method is working correctly, is ridiculously high.
These kinds of situations are no longer a problem once you start using automated testing. All you have to do is write a few tests with mocks and then you’re good to go. Whenever you make a change to your code, just run the tests and you’ll know for sure if you broke anything along the way.
Manual Testing Doesn’t Scale
A time will come in your development process where the amount of manual testing you will have to do to ensure stability in your app will become far too great to be practical. You may be able to get by without testing when building Tic-Tac-Toe. Anything, larger, however will become far too unwieldy to properly test for production.
Consider a very simple, Twitter-like application. You’ll have a login, profiles, tweets, retweets and a timeline. Say I want to go ahead and make a small change to my profile class, so users can like Tweets, I’m going to run into an issue. In one way or another all of these other systems rely on some functionality of the Profile class. That means if I make any changes to the Profile class, I’ll have to go and manually test that every single one of those systems still works afterwards. As your codebase grows larger and larger to add more features the amount of manual testing required will increase exponentially. This isn’t practical in any sort of production environment.
Wrapping Up
Whether or not you enjoy writing tests, the merit for them becomes clear shortly after introducing them into your workflow. The amount of time you’ll save, how much more confident you’ll be in your code and the ability to fully test your application, are benefits you won’t be able to ignore. Testing has made my life as a developer so much easier and every time I open a project without them, I realize once again just how necessary they are.