TDD best practice

In another post, Zed made the following comment;

> “What you want to do is get into a cycle of:
_> _
> Write some code.
> Write some tests.
> Review your code and tests.
> Run your tests.

I’m conscious that developers can often make assumptions about the simplicity of their methods/ functions and therefore skim over the testing part of this process, only to find they enhance the code at a later date and introduce regressions.

So, is a test-driven approach a better way to write code ‘just incase’? Would this help junior developers shape their code for positive/negative impacts and therefore improve code quality?

Or does this just slow the programming learning process down, if tests are written first, and then code to satisfy the tests?

1 Like

TDD is a very broad topic (in regards to developers having very varied and often religious opinions). Here is my take on TDD:

So, is a test-driven approach a better way to write code ‘just incase’? Would this help junior developers shape their code for positive/negative impacts and therefore improve code quality?

It depends. But mostly - yes, it is a better way to write code. Software is rarely developed by a single person, so tests are also in a way a documentation for any developer that wants to contribute to software. One needs to only run tests and see how the internals of the system work. So this speeds up onboarding of new contributors as well as prevent regressions from getting into codebase repository.

Or does this just slow the programming learning process down, if tests are written first, and then code to satisfy the tests?

TDD first and foremost is a discipline and as every discipline, it requires you to not only some time to learn and adapt your coding style/habits, but also constant practice. If you don’t practice it for a period of time - no matter how good developer you are - you will take time to “get into” it again after some period of writing just code.

Also my style of doing TDD is:

  • write test
  • make it pass
  • extract working code from test to its own file (be it method or class)
  • repeat
1 Like

I’ve found that mandating someone write tests first ignores the realities of problem solving, and the realities of how TDD fanatics actually code. Every person I’ve seen who is a TDD fanatic claims they write their tests first, but then I’ll catch them doing a “spike”, no tests, just hacking the solution. When pressed on it they’ll claim that this doesn’t count because it’s not the real code, but it does count. They spent some time free-form coding without obsessing over the order of things. What means is the real TDD process is:

  1. Spike
  2. Test
  3. Code
  4. Repeat

Well, #1 is code first. It’s not a test, so saying people should or must start with tests only when the entire process actually starts with not-tests first is disingenuous to outsiders.

In fact, you find this lack of self-awareness in almost every single thing I’ve ever studied. In guitar you’ll see top guitarists like Steve Vai claim he always keeps his fingers parallel to the frets, and then you watch him demonstrate this and literally turn his hand 45 degrees to the frets. In painting you’ll hear painters say don’t blend and then watch a video and oh look at that, blending all the time.

So, what I tell people is, do what is the easiest path to solving the problem, just make sure you have automated tests since the entire point of being a programmer is to make computers do work for you and tests are totally something you should be automating. This frees people up to solve the problem with the best heuristic they can at the time. Do they have a good idea of the steps in a process but not how to implement it? Ok, tests first might be the way to go. Do they have an idea how the code should work but not really how it should be used? Alright, start the code and then use the tests to figure that out.

I also demonstrate to people who I actually do it so they can see what I’m really doing. I tend to actually bounce in a cycle between test and code so fast that there really isn’t a first or after. I tell people to not write mountains of either test or code before writing the other, and instead do it incrementally using both to check that things are working. This is a much better way to work and I find it matches how programmers, even TDD fanatics, actually work.

The other thing I tell people is that there is a difference between personal processes and team processes. How you write your code is a personal process. How that code is verified is a team process. If the team has the requirement of “must have automated tests”, then that’s as far as I think they should go. It’s then a personal process for the person to make that happen. The flaw in almost all Agile methods is they take personal processes, which should be left to the worker, and try to impose them on the entire team as if every person and every problem is the same. This is a manufacturing mindset which doesn’t fit into the creative field of programming.

However, I do throw in the fact that beginners have almost zero personal processes yet, so in the case of training a junior programmer or beginner, imposing a process on them is just fine. As long as the process is actually something that the pros use and not something they think they use that beginners should do.

1 Like