Test-Driven Development (TDD) is a special case of test-first programming that adds the element of continuous design. With TDD, the system design is not constrained by a paper design document. Instead you allow the process of writing tests and production code to steer the design as you go. Every few minutes, you refactor to simplify and clarify. If you can easily imagine a clearer, cleaner method, class, or entire object model, you refactor in that direction, protected the entire time by a solid suite of unit tests. The presumption behind TDD is that you cannot really tell what design will serve you best until you have your arms elbow-deep in the code. As you learn about what actually works and what does not, you are in the best possible position to apply those insights, while they are still fresh in your mind. And all of this activity is protected by your suites of automated unit tests.

You might begin with a fair amount of up front design, though it is more typical to start with fairly simple code design; some white-board UML sketches often suffice in the Extreme Programming world. But how much design you start with matters less, with TDD, than how much you allow that design to diverge from its starting point as you go. You might not make sweeping architectural changes, but you might refactor the object model to a large extent, if that seems like the wisest thing to do. Some shops have more political latitude to implement true TDD than others.

Source: https://www.versionone.com/agile-101/agile-software-programming-best-practices/test-first-programming/