While I’m not a fan of using TDD all the time, here are a few situations where it’s effective.
Bugfix
Starting a bugfix by writing the broken test case is often very practical, especially with issues that show up somewhere in the front end, but the fix is somewhere deep in the logic.
Unfamiliar source or feature
If your feature breaks another team’s scope, it’s often very difficult to trace from scratch. Instead, writing a failing test case in one of their existing suites is much more efficient.
Feature setup takes too long
When a bug is buried deep within feature switches and multiple settings, it’s much easier to set everything up in a test case, rather than manually.
Build takes too long
If you’re in an unfortunate position where the build takes too long, making it very inefficient to make a change and then wait for the build to test it, doing that through unit tests is almost always much faster.
Reproduction takes too long
If reproducing a bug or feature takes multiple steps, writing a test case is once again the way to go.
Legacy code
And finally, TDD is very helpful when working on legacy features.