Especially when writing UI tests, the scenarios we need to automate can be quite large. They involve a lot of steps, they need to interact with a lot of page elements, hence they are more prone to failure if not paid attention to. In order to write the best automated tests for such cases, we should really do it in small increments ✅
Define the tests to automate
Before you start automating your scenarios, it should be quite clear what the steps of the test are. Either you already wrote down a manual test case that reflects the steps required, or you have complex requirements as a basis for your tests.
In both cases, you know exactly the order in which the steps will execute. You also know what page interactions are required. So in theory it should be very simple to just create automated tests and run them.
But if you create everything at once, you might have a few surprises. Maybe there are some steps that were missing from the test cases or requirements. For example, it can be that these steps are now needed because of some limitation of how the software can be written, or simply whoever wrote the scenario forgot about them.
In this case, you need to figure out exactly where you need to insert the extra test code, and sometimes that can be a bit tricky.
Using small increments in automated tests
Another surprise you might get when running this large automated test is that you have random failures at different steps in the test ❌ This makes debugging really difficult: you need to debug too many things at once, that might not reproduce every time.
So, now you want to debug one step, but it passes. Then you try again but there is a failure there. You try again, but now the failure is somewhere else. Commenting out parts of the code would make it easy for debugging, but then, why the need to have written all that code from the start?
The better approach is to write tests in small increments. That means: start off with the first chunk of steps and carefully automate them. Once you are happy with the results, run this chunk of code multiple times. In case you have any failures, it is very easy to debug and find the culprit.
Of course, fixing the code will also be very smooth, and you have much more context of what happened in the test up to that point (as opposed to already having run dozens of steps). Once you have successfully fixed any issues in this first chunk, run the test again multiple times, to confirm the fix, and to confirm no other random failures exist in this code.
Then, add the next chunk. Run the entire test. At this point, the only failures you might have should be from the second chunk of code you implemented. That is because you already spent time running and fixing the first chunk. So any failure should be easy to identify and localize at this point. Once you are done with any fixes, again run this chunk, multiple times 👨💻
And of course, you should continue implementing the remaining steps of the code, until you are done with the entire test. By the time this happens, you have already re-run the test quite a lot. Therefore, you should have identified any points of failure and fixed them all. This entire test should be ironclad.
Of course, sometimes, you might still encounter some failures, but those should be really rare. After all, you did run most of the code tens of times already, especially the first parts.
If you refer to my previous post on creating tests as calls to methods representing the test steps, you will see that these increments for writing the tests can be those methods. Start with the first method. Implement it, tweak it, and make sure it runs well.
Once you do that, you can actually easily use it in several tests already. And that is because you wrote it once, made it reliable once, and you can use it as many times as you want 😃
In conclusion, it is best to write your automated tests in small code increments, to allow for easy debugging in case any failures occur. But there is also another aspect to consider: if your test is too large, you might be able to break it down into individual tests, instead of having a very large one. Reading, understanding, debugging, and fixing a huge test is never an easy task.