For me, it's about an 80/20 split between writing tests first, and writing the implementation first.
If we're going to dive into strict definitions. It's not TDD if the tests don't come first. The first 'D' implies that writing a test drives your code in a certain direction. Writing a test after writing the implementation it verifies doesn't drive your code anywhere - it just tells you things you already know.
As for why I write tests first so often: It's mostly a habit at this point, I've been doing it for so long that it's just how I write code nowadays. Writing a decent chunk of code without a test or two covering it genuinely makes me nervous...
You're also totally right that, in a whole bunch of cases, it's impractical to write tests first. And it's in those cases that I put on my code-cowboy boots and just start rattling out code to verify later. But, I also believe that the cases where it's impractical to write test-first code are much less prevalent than many would suggest.
A good example is when you're writing some complication function, but you haven't worked out the approach you want to take. It's very common at this point for developers to abandon writing tests, in favour of "feeling out" the problem and testing it once they know it's right.
All I would suggest in the situation is to write a coarse grained test that at least verifies that the expected output is returned for a given input - forget the implementation details. Then let it fail. All day if it has to, and use that test as your measure of whether your implementation is correct or not.
There's no need to write a finer grained test if you don't want to. But simply coarsely covering the behaviour of a function means you'll spend much less time debugging and console.log()-ing as you write your implementation.
Like any tool or skill, TDD has many nuances to it, and it takes years to master (if it's possible to master at all). What I've found after a few years of pushing myself to write tests first is that overtime, the cases where I feel like I can't write tests first become fewer and further between.
We’re a place where coders share, stay up-to-date and grow their careers.
We strive for transparency and don't collect excess data.