There is no doubt that tests are super critical and we must write it. However, I am curious about your approach to it, do you follow TDD religiously? Or you write tests after writing actual code. What's your experience with TDD, have you found it to be effecting the design of your code in any way?
There is a common misconception that test driven development is slower than development without tests. I've been doing this job for nearly 20 years now and I can state with confidence that over the course of a project's lifetime this is simply not true. But we're writing more code, right? How can that not be slower than writing less code? It's simple really, the code you write is more focused and your test harness massively simplifies refactoring (an inevitability of an evolving system) and regressions are inevitable without some protection. It's actually quite easy to tell from the outside whether a project is using tests properly by the regressions you see as new versions are released. See the same bug pop up a few times? I guarantee that project either isn't using tests, or isn't using them properly. Writing tests after writing the code is a really good way of writing really bad tests.
That said, not every project needs tests. Sometimes you don't even know what it is you want to do (let's say we're working on something experimental or trying out an idea), and in this instance writing tests will almost certainly slow you down unless you adopt BDD too which allows you to define behaviour at the very highest level and gives you some focus moving downward into specifics.
I write unit tests only for code which broke during the development phase and of cause after shipping. But I write test scenarios and test plans for integration tests before coding. Because the chosen technology stack or the exchanged technology stack must pass the integration tests.
I do this because I'm confident enough trusting my language/platform/framework/library/skills. It makes no sense to me to write tests for stupid/simple/pure functions like logging or doing additions and the likes.
The type of projects I work on, typically don't have test cases until it's in production, once it goes into maintenance mode, then tests cases might be added. Test cases slow you down a lot if you need to move quickly with a very small team.
Larger long-term projects will have test cases, but only enough to ensure business logic stays sound and once it goes into maintenance mode, more test cases will be added.
The side-effect is that we can't do daily deploys and each deploy requires a human to sit and test through the scenarios - which is fine for a system that's rapidly changing at such a pace that test cases will become invalid faster than they can be written.
So, here's how we do it (in the context of SCRUM with 2-week sprints, thereby keeping design/code/test/deploy cycles short).
We write down acceptance criteria and expand on it with architectural requirements/goals.
We do a high-level architectural design with the team so we can agree on an approach if needed.
The UI design is also napkin-sketched with the UX people.
Then, we literally evolve the code using TDD where possible:
This happens concurrently for the back-end and front-end, frequently checking that we match the criteria and sketches (design approach and so on) and doing all the good things like CI. Once we're ready for an internal review, we first run it through Sonar Qube to increase coverage where we feel it's needed and increase code quality.
All the above happens in a continuous integration (and deployment when appropriate) pipeline using Go-CD (with maven, some plugins and special Websphere deployment toys).
Cliff Rowley
Thinker, Tinkererer, Dork.
I have seen both sides of the coin, and I can assure you TDD is what you should follow. The best approach varies from person to person & company to company and largely depends on the culture, so it will be better if I tell you what we do here @ Unbxd. Lets say I have to write an application, here is what I would do.
What happens with such an approach is you have a better clarity on what you plan to write and the code is bug free.
Yes, you start thinking much more clearly. As I mentioned, you will have to identify various points which can be made pluggable, then there is an added advantage of you not writing anything until everything is clear to you. 90% of the bugs are caused by incoherent ideas and bad design.