The reason I like TDD is that the feedback I get from it is very close to what I'm working on at the time, which I believe shortens overall development time.
As part of TDD, mocking is valuable because it allows one to handwave around parts of the system you don't care about at that moment. "Assuming this other method I rely on works..." can save a lot of time in setup and, again, tightens up the feedback loop.
For what it's worth, I think both isolated tests and system tests have value, and I do both of them. I think relying on only one style is limiting and shortsighted.
The problem is that TDD only works in a subset of problems and programming languages, but it gets sold as the ultimate solution.
I am yet to see usable TDD approaches for strong typed languages in projects with dependencies to third party binaries, specially if those binaries are native code.
No proper way to design and test UIs, complex algorithms and data structures with TDD.
I'm not sure I understand. I've written thousands of tests over the years in strongly typed languages, with third party dependencies. Further, I've written complex algorithms and data structures with TDD (in fact that tends to be when it is most useful).
UIs are more complex to TDD that is true, but at the very least I've found that because UIs are hard to test, TDD drives you to put the least amount of logic in the UI layer, which is a very good thing.
I've still haven't found a satisfactory way of doing TDD with UIs. Being able to do MVVM with WPF got pretty close but it felt a lot more like driving the application with selenium or something akin to it. iOS seems worse, but I've only dabbled in it.
The use of a third party black box with side effects in your architecture is going to have obvious and difficult impacts on the design of your system. In order to minimize this impact you will need to isolate that code dependency from other parts of the system. There are many ways to accomplish this isolation, dependency injection is the most obvious one and easy dependency injection is one benefit of some dynamic languages. That isolation is not a result of TDD, it is a good design principle that TDD helps enforce.
As for cache cohesion, algorithmic complexity, etc. I wouldn't encode those in a test any more than I would encode a requirement to use while loops vs. recursion. I've never encountered a specification that cares about those things, rather typically you care about some performance metric, median latency, worst case latency, sustained throughput, memory usage, cpu utilization, etc. If those things are important enough to be specified, they are important enough to be automatically tested. Writing performance correctness tests first has all the same advantages as writing algorithmic correctness tests first, and I heartily recommend doing so. If I ever encountered a specification that actively cared about memory layout, I would first be suspicious of the requirement but if it turned out to be real I would spend a lot of time figuring out how to test it.
I suppose you're correct. We are starting to do some image-diff based regression testing, but I'm not sure that anyone really does css TDD.
TDD is in large part about getting the feedback-loop cycle as quick as possible while you're developing. JS unit and integration testing can help with the functional aspects, but visual aspects are better paired with a tool like livereload.
As part of TDD, mocking is valuable because it allows one to handwave around parts of the system you don't care about at that moment. "Assuming this other method I rely on works..." can save a lot of time in setup and, again, tightens up the feedback loop.
For what it's worth, I think both isolated tests and system tests have value, and I do both of them. I think relying on only one style is limiting and shortsighted.