A year ago I stumpled over one of the best article about test driven development I ever read. Event the title is crispy I mean Stepping Through the Looking Glass: Test Driven Game Development how cool sounds that? Noel did a decent job to explain the mantra (write a test, see it fail, write code, see it proceed, refactor test, refactor code), the use of mockups and the idea of fixtures. There are 3 parts and they are definitly worth reading it. And you will not believe but those articles are over ten years old and still relevant still fresh still entertaining.
It tooks me some times to wrap may head around that fixture thing but it was one of the biggest beneficial idea I've ever heard. A fixture or I also call it sometimes "The Story" of a set of tests helps you perfectly organize your tests and keep them understandable to the max. Together with a workmate I improved the idea recently with a base fixture where we introduced a base story or an introductional story. All succeeding tests which releay on this introductional story inherit from this base fixture. This makes your test readable from top till down as if you would read a book or a text. Before that I copied several identical lines to several fixtures or wrote helpers but I do not like helpers as you can do often not understand at a glance what this helper is, is it part of the software or only for testing. But with the base fixture I just can read it top down to understand and see at a glance what I screwed up. A base fixture makes clear it is not part of the software but for test purpose only.
My workemate and me improved as well the idea of the mockups. Today we often write EmptyTestFoobar objects which inherits or implements the Foobar object and throws an exception for every method you can call. Just that. It is extremely helpfull to test older parts of the software, as we just inherit from this EmptyTestFoobar and inject it instead of Foobar itself. Now when we run the test we see which methods the software do call on certain actions. As well we can this way make sure that the software never calls a specific method without our knowledge.