The main benefit for TDD in my mind is that it mostly makes it painful to write spaghetti code. When I'm reviewing something that looks too integrated, I just ask for a unit test for that particular piece of functionality, and the author is effectively forced to go back and refactor. After going through this a few times, they learn to think about their design before they write code. Of course, many dynamic languages defeat this by offering hacks like Python's mock.patch which let you nominally test spaghetti code...
Interesting that you mention dynamic languages. I think that a lot of why people do TDD is that you can't reliably know if a program in a dynamic language has basic issues unless you run it.
The same is partially true for manual memory managed languages.
You need to push towards 100% coverage in order to replicate the advantage you get in a statically typed language like Rust.
Yes, the better static analysis you have, the less you need to depend on runtime checks, but Rust makes a lot of tradeoffs which ultimately make it a poor choice for most application development (steep learning curve notwithstanding). There's a whole suite of static functional languages that give you the same strong static guarantees, but without the headaches of borrow checkers, lifetimes, boxes, etc, etc. Beyond that, there is Go which gives you some rudimentary static typing (a 99% improvement over dynamic languages), world-class tooling, a great deploy story, etc. In my mind, Go is the sweet spot for the demands of modern application development.
TDD is about creating tests for your requirements, and then writing code to make them succeed. The reason it doesn't work is because most medium/large feature changes don't fully realize their scope and requirements until they're well along into development, making the earlier tests an unnecessary drag.
Writing unit tests at all is independent of TDD. After you get the feature working, you write those to verify the program does what you think it does and to think through failure scenarios. Most importantly they make sure that future changes do not break the functionality you just implemented. I think asking for unit tests is important for any true bit of functionality in a large system.
Fair enough. The benefit of TDD them in my mind is that it keeps undisciplined developers from wedding themselves to a bunch of untestable code and then getting frustrated when asked to add tests in a code review. Whether or not this is the stated purpose of TDD is a different matter.