44 Comments

Unfortunately, most of the developers I have worked with had either never heard of TDD, or thought it a ridiculous concept. Yet those same developers were often terrified of the code and took ages to release any change, because they wanted to make sure there were no regressions (either through manual tests, or static analysis of their changes).

Some may sneer at the "Ease" outcome, but my anecdotal evidence suggests that most programmers have more anxiety about changing their code than they would like to admit.

Expand full comment

So much compressed toxicity in a single sentence and then accusing you of that , talk about reality bending.

I have seen elsewhere on youtube comment that you are trying to "shove TDD down our throats" my god...

At least he got one part right you are definitely influential , please keep up your work.

Expand full comment

It's time for the First Feedback Filter--what of that comment is really about me & what of that comment is about him? Pretty much 100% him.

Expand full comment

Having practiced and proselytized TDD for 20+ years (I bought TDDBE when it was hot of the presses), the most common reaction I hear ( with whatever rationalization layered on top ) is that TDD "feels weird". It think a big part of that is the way TDD slows you down, since most devs pride themselves on thinking about 5 things at once, and enjoy the rush of keeping all the balls in the air.

There is definitely a learning curve to the practice, and it requires a bit of discipline at the start, but it is the single most powerful technique for programming that I have ever learned.

I usually recommend to people to do what I did originally: find a small project and commit to totally strict TDD, accepting that it will feel like kindergarten at first.

Like any advanced technique, it takes some time to get used to and master, and once you are in the swing of it, you can tailor it to the rest of your style.

Expand full comment

Yes, it feels weird - because it is not the way we learn to code.

Most people start by thinking of how they will solve the problems for which the program is written. Computer science courses and job interviews emphasize that the most important thing is knowledge of algorithms and data structures - and when working against existing code or interfaces, they experiment to find out what works.

TDD emphasizes how the code you're writing will look from the outside, rather than how it solves problems. Until you've learned to work that way, it feels very backwards. That's why so many developers code first and write unit tests afterwards, if at all.

Expand full comment

I agree it's not how most people learn to code.

But the explanation doesn't resonate. I find that TDD encourages me to think MORE about the problem and it's solution.

When I write a test to start work, I ask myself: "What would the solution to this problem look like?"

The code quality benefits emerge from the process of refactoring, they aren't what I'm focusing on.

Expand full comment

Just had a random thought about this: when someone criticizes TDD because it "feels weird", they've just admitted that how they feel while programming matters. That's a step in the right direction. Or at least, I feel like there's some conversational jujitsu you can do to redirect that energy towards nonharmful ends.

Expand full comment

Riffing off what Russell Gold said—I view TDD as "using what you know to scaffold learning what you don't". For an experienced TDDer, that often means using specific examples to scaffold the elaboration of a general algorithm. But non-TDDers often aren't comfortable with their test frameworks, and don't know how to design good tests. What they know is production code, so they'd rather use that to scaffold learning about the tests than the other way around. Put another way: writing tests makes them anxious and uncertain. When they hear that TDD is supposed to *reduce* their anxiety, that makes them defensive. How could it possibly feel safer to do the error-prone thing first?

TBH, this is how I feel about writing tests for user interfaces. The tools for it (e.g. Cypress, Testing Library) seem so annoying, complicated, and error-prone that I either don't test through the UI, or I put it off as long as I can. (I hope I'm really empathizing with non-TDDers based on this experience, and not just projecting.)

So, one strategy for bringing skeptics into the TDD tent could be:

- Get them writing tests at all. Most programmers admit (even if grudgingly) that unit tests are a good idea.

- Teach test design and testable design.

- Get them to work in smaller and smaller steps.

- Get them to test their tests by making them fail.

Expand full comment

Thank you for the post. An outcome that TDD brings me is to help the design process. I feel more comfortable choosing names and making decisions for classes/methods/parameters when I write them first inside a test case.

Expand full comment

What happens with TDD, also with Agile in general: Deeper truths and values that make overall sense lead to a certain set of techniques that apply in a given context. Over time, some people forget about the truths and values and focus solely on the techniques. Applied to different contexts, those techniques fail. It is then deduced that the techniques are BS.

Expand full comment

One of my sweeping generalizations is that people who make sweeping generalizations, particularly, people who make dismissive sweeping generalizations, are stupid. Ceci n'est pas un pipe!!! Your comment is 100% on the money. This is why, I am really interested in Agnostic Agile which basically looks at Agile techniques and tries to present them in a buffet style, so you take what seems to be the best fit for your team and project.

Expand full comment

I suspect the anti TDD crowd is individuals working in large companies. When you're working in a large company you have a bunch of other developers and dog-fooders to tell you when your code is broken. So the cost of the feedback loop is lower than when you're a solo dev (me!). It's still higher than having it caught immediately, but not as bad. Now this cost doesn't include the broader cost to the company, but just the cost to that one individual.

In my case, as a solo dev, if I introduce a bug, it might take weeks or months before I catch it or figure out the root cause, by which point I've forgotten the context of the change. The cost of a bug is crazy high, so I have to delay features with a much more higher focus on reliability than if I were at a large company. Hence I'll take the small cost of writing tests first.

Expand full comment

I think its not about if you are simply pro or anti TDD , it is calling "bullshit" an entire body of work that involves books , blogs , presentations and so on without engaging in meaningful discussion.

Expand full comment

Seems to me that there is a deeper issue at work that gets papered over by the hyperbole. Are developers responsible for writing reliable code? Nobody is going to _say_ no, but some folks sure do act like it.

Expand full comment

Yes you have talked about it before and judging by all the gated qa silos the answer is no. I think a very big factor is habbit here , when folks have worked the same way for years and years the paradigm shift is too much , "why do you get to say how i work sucks" , "i have always done that and have no issues".

Expand full comment

I don't think that's fair. What I think is fair is, TDD controls how a person thinks and some people think differently. If you are naturally a top down person, TDD is very difficult.

Expand full comment

How is that not fair? I'm not saying "if you don't TDD you're irresponsible". You can write tests after & be responsible. You can thoroughly bench check a la Cleanroom & be responsible. You can extensively manually test & be responsible. Is it fair to say, "If you are being responsible I should be able to see it in your workflow"?

Expand full comment

In that case, I actually agree with you.

Expand full comment

This is a very valid point about general arrogance of dismissive stupid people I totally agree with. Huge difference between saying, "I don't think this technique is appropriate for me or my project (right now)" and saying "I don't think the technique is useful to anybody at all". Obviously, the technique is valuable but a huge number of people certainly have used it.

Expand full comment

It's great to see a "Known restrictions" text from one of the main proponents. I did not look through all the comments, but it seems to me the "Cost vs. Benefit" aspect is missing.

From my restricted point of view (SAP development at an SAP customer) I think the following aspects are important (all pertaining to TDD, as well as UnitTests in general - so maybe this is off-topic here):

- How frequent (if at all) will the code be changed in the future? How likely is it that this will break anything?

- How likely is it that critical errors will be overlooked (in initial test, and in future code changes)?

- How hard (how much overhead) is it to write the tests, especially to provide test data / mocking?

- What is the ratio of "real errors" caught by the tests, vs. adaptions to the test methods?

- How much time (and knowledge) do these adaptions to the test methods take?

Expand full comment

My team adopted TDD this year and I am now a huge fan (on the other hand, I've written on here a couple of times about TDD and gotten mixed reviews after sharing with Reddit and Hackernews).

Automated tests have caught SO many issues for me before going to staging, and they let me know where all the breaking changes are when I do change something. I'm a lot less anxious about changing things because of it.

I think there's another important point to bring up here though - if your code coverage isn't high enough, it won't catch some breaking edge cases, which reduces developer confidence in the test suite as a whole when either QA finds a bug or the tests don't catch a breaking change ("What's the point of writing all these tests if my software is still buggy and untenable??").

If there's one thing I've learned, it's that TDD is a culture which has to be adopted in its entirety in order to work. I believe this is the hardest part, because you have to constantly be on your team about practicing it - which unfortunately for them includes sending back PRs due to missing tests.

But in the mean time, I'm going to enjoy the serotonin boosts from the tiny green success toasts.

Expand full comment

I totally agree with the desired outcomes, but I don't use TDD. I have tried the approach numerous times in my career, but I find I waste time rewriting both code and tests. I can achieve the desired outcomes, including full test coverage, more quickly without TDD. But that is "just me". For others, TDD may be helpful. So I don't think anyone should disparage the pro-TDD nor the anti-TDD crowd. I've been coding for 40 years. I am good at it and passionate about it. If you ask anyone I've worked with I'm sure they will tell you my code is great. It is not about the path we take to get the results, but the results that are important, at least to me.

Expand full comment

Great post and great discussion - thanks everyone!

Also, "Bless your heart." Are you a Southerner? 😉

Expand full comment

I’ve been exposed to midwesterners

Expand full comment

And TDD gives me user empathy because it forces me to be a customer of my code to ensure the interfaces make sense and work well. I find the cost of those kind of issues also fairly high (without TDD)

Expand full comment

"An influential autistic developer" is a pretty ableist* statement. WTF. I don't know who is being accused of being autistic, nor do I think their autism is relevant because I absolutely know LOTS of non-autistic software developers who swear by TDD. The advantage of test first is, you are then guaranteed to be able to test the refactored code. That is a selling point. Lots of people, especially under time pressure certainly don't test after. *I am up in the air about "wokeness" sometimes but it's still rude and unprofessional for people to make statements like this.

Expand full comment

He was looking for something to lash out at. He could have said bald, or old, or whatever.

You know what this reminds me of is someone who is afraid of admitting something about himself so he criticizes that thing in others, like how some of the biggest gay bashers turn out to be gay.

Expand full comment

Indeed. It's certainly true that great software developers exist who are any and all those things. If I do comb overs, do I count as bald?

Expand full comment

Great article. I love this part: "You & your customer deal with the consequences."

Maybe we, as a developer, we don't see the consequences as we should. Most of the time they are not visible to us in a clear way.

So we may think that a cool practice like TDD don't bring much value because we are "safe" the way we work.

I love TDD, but maybe I have this opinion because I had a direct contact with my client and users. And I dont want neither of them sad or mad about my work. The consequences were clear to me and my team. So, we love TDD and testing in general because, in the end, we got happy customers. And we could work in a sustainable way.

TDD helped a lot in understanding the problem before solving it. We developed an ability to question every important details that we could miss before the practice of TDD in the team.

I wish more teams and individuals had this experience.

Expand full comment

There are other ways to have peace of mind and happy customers, but there are lots of ways not to have peace of mind & unhappy customers.

Expand full comment

I like to use my tests as a contract with the stakeholders. I'm a Ruby on Rails dev, and I find RSpec, written well, can be read by "normies" before the "it" blocks are full of assertion code.

This often drives the discussion of "happy path/sad path" in directions folks don't normally think about. Plus, collaboration in this way will often net a tighter solution to the problem the feature aims to solve.

So, that said, TDD is not only good for us code nerds, but serves as a bridge of communication as well.

Expand full comment

My issues with TDD are that I tend to think top down and it doesn't feel natural. I however do love the idea of it in terms of having the code coverage allowing easier refactoring and would love to try working on a project with TDD in place.

Expand full comment

It doesn't bother me that different people think differently. It doesn't bother me that my preferred workflow isn't optimal for everyone. I fervently disagree with those implying that developers shouldn't be responsible for writing reliable code (you're not saying this tbc).

Expand full comment

I am certainly in agreement with you here. We are responsible for the reliability of the code we write and for it being easy to understand. I don't know if it's valid but I think of TDD as a Micro agile "best practice" whereas I think of for example Scrum or Kanban as macro best practices. Code correctness or incorrectness can occur at multiple levels. The selling point for TDD that I cannot escape is the promise of being able to confidently refactor code but this assume that the high level models around which the code is built are correct. If you write perfect code addressing the wrong problem, you are still screwed.

Expand full comment

I'm not sure I understand your objection. I hear that TDD feels unnatural for you, but I don't think top down thinking is the problem, because I often work that way too. Dummy out the top level process, then drill down, adding more detail as you work down the levels.

Expand full comment

It probably would help me a lot is I could find an open source project that enforces TDD in its development process. Seeing the code base, the way things are set up, would help. Mostly people illustrate with trivial examples.

Expand full comment

Having enforced TDD on team projects before, I'm not sure this produces the desired outcome...

The key skill is writing good tests i.e. formulating a code description of the desired outcome at the right level of detail. I really recommend starting with small, but interesting, projects.

Another approach (again with a small project) would be to write the code, write the tests you think demonstrate the functionality, then throw away the code (!!) and reimplement by adding one test at a time to a new project space. This will help to evaluate the quality of the tests and work the mental muscles that are needed to master the technique.

Expand full comment

It's always hard to escape the ghost of unintended consequences but I think, I'm kind of looking for a project that presents the technique as it should be and indeed as it would appear to the outsider entering the project. It's a given that no amount of process prevents abuse. Doing my own thing, probably has value but I'm interested in the Gestalt in a project worked on by people who believe in the technique and worked on it together.

Expand full comment

I'm shocked by that comment. Recently I got into a different argument about the necessity of 100% test coverage and been labelled "religious", because I cited sources that some parts of the code are either very hard to test or not worth the effort. I got this from the other side of TDD where no code should exist without it.

While I have practiced and mentored teams for years on using TDD, and it was really valuable when working with others or taking over legacy code; when I work alone - may it sound weird - I found that sometimes I do TDD in my head. I just break things down into tiny behaviour changes make them, test manually; commit and move on. But if and when I open these codes up to others I always replicate the code from TDD first approach (ending with the same result and same architecture, unless I've learned better ways to do them).

So for a team I prefer test first approach, when alone, I test as I think necessary.

Now you can throw the stones. :D

Expand full comment