Writing good software
The difficult part of writing good code is understanding the problem you are trying to solve.
The easy part is when you code it.
In reality you begin with some understanding of the problem and jump into coding.
You realize your understanding is inadequate on many fronts.
You stop coding and work on your understanding.
You repeat this until you got the perfect understanding of the problem, and the code reflects it.
As you iterate on the coding-understanding-coding, you would have tested few scenarios. Some end-to-end, some at the function level. This would have exposed gaping holes in your understanding of the problem.
Whenever you find holes in your model of the problem, it is better not to continue coding. Fix your understanding.
The better you understand the problem, the simpler it begins to look. This is when the code will convey the solution better.
Coding something purely by testing the outcome is a bad idea especially if the problem you are solving is complicated.
This is because when you modify code based on a bunch of tests, your attention is on to make the tests pass with short-term changes, and you lose sight of the broader objective of writing the code based on a deeper understanding of the problem.
Debugging and testing a code with partial understanding of the problem is also an ineffective use of your time.