TDD is ~95% practice. The theory about it is really simple and you may already know the Red-Green-Refactor cycle and what to do in each step. Practice is harder, and it's always beneficial to have some guidance as you practice it. Here's a quick list of six things that work for me, and maybe can work for you.
Analysis Paralysis not allowed: Sometimes we think too much, and thinking is good but it's also time-consuming and it's better to spend the time building your program, rather than thinking how it should be done. Questions like "how do I call this test?", "is it better to create a separate object or not?" appear all the time. Those kind of questions are ones that you need to ask yourself after your test is green, not before. And maybe you haven't built enough to have an answer, so don't lose much time on them, TDD will guide you sooner or later to the answers.
Do not forget step 3: Sometimes we make a test pass and we go immediately to the next one. But step 3 (refactor) is an important step, because you can fix the tech debt you just left. It'll be harder to fix later. Check namings as well! And don't forget to refactor the tests. Think about the interest you can accumulate by leaving tech debt. Don't hurt your future self ;)
Assertions first: in the Act-Arrange-Assert pattern, I like to go from bottom to top. This will help you focus on getting what you want, and then writing all the context you need to make that happen. At the end you will probably have the minimum context you need for the test. Simplicity is a big win here. Nobody wants to maintain tests with lots of set-up lines of code.
Break anxiety: Sometimes we have an idea of what our final solution will be, and we cannot resist to code it and then we break the TDD cycle (I confess! It happens to me every day). We lose the flow. We might be introducing a bug (we always tend to think that our solutions are unbreakable). Do not think that because of TDD, you are going slow. Think about the long-term benefits. Starting again the cycle after you broke it, it's also time consuming. So it's better to go at a constant velocity, without taking "shortcuts". If you do a lot of cycles, you may probably notice that you have already accelerated it.
Leave edge cases to the end: Edge cases are usually hard to test, compared with the happy path. And they are not too valuable if you don't have the happy path already covered. Think about the future users of your system. What will be the first thing they will try to do? This should be your priority. Unless you are really sure about what you don't want to happen in your system.
Feel free to take another path if you are stuck: Let's say you are stuck in step 2 or even in step 1 trying to get a green test. I suggest that if you are more than 10/15 minutes stuck, you need to do something else to move on. Diverge (leaving the test unfinished and trying another) or rollback (deleting the current work and starting with another test) are both valid options. In TDD we are always following a path, and sometimes it is wise to take a step back and change the path.
- Do not let anything block you.
- Do not miss opportunities to improve.
- Start small and unperfect, and do small steps.
And you will rock!