"Tests Are a Waste of Time"

Last updated Mar 8th, 2023
Oh, boy.

I want to tackle a hot take that happens to be one of the biggest ones holding developers back from endless puppy videos becoming truly indispensable software designers.

We're on a mission here to learn the first principles of design, testing & architecture.

That's going to open up a LOT of doors for us.

Now, here's the thing I hear all the time:

"Writing the test first (TDD) is a COMPLETE waste of time".

Ah man, that's a shame.

Front-end developers, I'm looking at y'all.

But, I do know how we got there...

I've been there myself.

  • You've tried TDD and realized — compared to the way you currently do things — it's pretty annoying
  • And since you can still make your code work without writing the test first...
  • It just seems unnecessarily challenging to approach your work this way

Totally.

And if you're a front-end developer, you may have heard things like: "write tests, not many; mostly integration".

Or that functional programming doesn't need tests (and that you're doing FP by using the function keyword...)

Or that all you need is E2E tests.

Ahhh... geez.

Many crafters ah've met.

And many I've lost to the most unfortunate Bad Testing Advice rabbit holes.

Most devs follow the Best Practices ™️ of what the official docs for their framework say to do (such as using snapshot tests — don't do that).

And then there are tools like Jest and Cypress, which are fantastic, but to be fair, they can't really give you the foundational design, architecture & testing wisdom you need in order to know how to use them correctly.

That's why we place 90% of our energy on skills > tools in the Phronesis Labs and Software Essentialist communities.

But just like you want to ensure you've got some good grip strength before doing a 200lb deadlift...

We need to get our mindset right before we embark on this path of skill development  where we'll master The Lost Art of Writing Scalable, Testable Code.

To explain why this take is a massive wrench in your growth plan (though there is a caveat), I'll give you a three-part response.

Ready?

Here we go.

1. The Entire Purpose of Professional Software Development is to Guess

What do I mean by this?

Well, just like there are a ton of different ways you can play Super Mario Bros (you can Speed Run it like a manic, play for "leisure" with your partner  yeah right, or collect the coins on each level)...

There are also a number of different ways you can play The Game of Software Development.

You can play:

  • the Code-First Mode: where you just care about building & making things work (as they occur)
  • the Exploratory Mode: where you're just trying out new libraries & frameworks, having fun with them, and it's pretty light
  • the Professional Software Development Mode: where the focus is on scalably, sustainably producing artifacts of value

I'm willing to bet that you want to get paid for your efforts, so that means you'd like to see yourself as a Professional Software Developer.

Me too.

What is Value Anyway?

Very simply, the way I think about value is this.

Value is anything that makes you feel good or gives you time back (so that you can spend that time in the pursuit of trying to feel good).

This is a key part of Essential #1: Software Essentialism, because setting up these variables that we'll use throughout the entirety of craftship journey allows us to move strategically and make good (design, architecture, testing & overall product) decisions.

Another key thing to recognize is that everything is a state machine.

Including Humans (that's you - I hope).

It's always been state machines

David K. Piano was right, everyone.

Here's how this works.

From Pain → Benefit = Value

It's simple. We don't like pain. We like benefits.

You create value when you take someone from pain to benefit.

Value summary

From Benefit → Benefit

It is also staying IN benefit.

Benefit

Example: Thank you Facebook for reminding me that Grandma's birthday was today.

Example: Your email service continuing to chime along and work swimmingly, as it did last week.

Negative Value

But software can have the opposite effect as well.

It can make you frustrated, feel dumb, silly, and bad about yourself.

This effect is NEGATIVE VALUE.

Pain

Example: Your email service all of a sudden stops working the way it used to.

Example: The UX to order a bowl from Chipotle on UberEats is so confusing that you accidentally order literally just chicken, nothing else - and you do that twice in a row by accident and then they ban you from the store because they think you're trolling them.

Example: Instagram changes the placement of the buttons for the 13th time this month.

This sucks.

The Guess (it's Theoretical & Physical)

Know what this means?

That there are at least 2 things that we don't know for sure.

  1. If what we want to build is valuable (theoretically, does someone even want this?)

    • Ie: "Hey everyone, I'm going to build an Anime Debate App so you can all stop using Discord now, and use my app instead :) ...anyone?"
  2. If it will work, and won't result in Negative Value (physical)

These two planes of Guesses have a ton of sub-guesses within them.

We make Guesses at:

  • The Theoretical Plane: with at least 3 different Guess Points
  • The Physical Plane: with at least 8 different Guess Points

Guess Points

And the only way for us to verify that our guesses are correct, is to perform Essential #2: The Feedback Loop.

This is also known as Three Ways.

3 Ways Expanded

This is just TDD at the 8 Physical Levels, but holistically, this is the entire philosophy for how Professional Software Developers play the game of Professional Software Development. This is also business owners, product people - essentially, anyone involved in playing the role of "creating software artifacts of value".

Strategic, Pragmatic Guessing

Now, I know what you're going to say:

"You can't possibly expect me to write the test first for every single one of those feedback loops. that doesn't make any sense. I'll just E2E test the most important features. That's enough."

And you're absolutely, 100% right.

Sometimes, it's non-strategic to spend time Feedback Looping over more inner-layer Guess Points.

For example, if your app doesn't have any customers (no value just yet), it doesn't really make sense for you to TDD your way through. You should be focused more on patching through to creating value for the right people.

At that point, with a fresh, new product and a ton of uncertainty, yeah, go right ahead -- go wild with whatever frameworks you want, because your focus is NOT on The Physical just yet.

It's on The Theoretical.

Focus on getting at least ONE Theoretical Guess correct.

In Part 5 of The Software Essentialist titled "Bridging The Gap (Theoretical → Physical)", we apply this process and learn how to identify, design, and build your own product of value, from scratch.

After one of your Theoretical Guesses connects, and you've created real value for someone out there, your goal should shift.

It should shift to the balance between:

  • Finding New Value
  • Maintaining Existing Value
  • Preventing Negative Value

Sounds straightforward, right?

Until it's not.

Seriously.

It's much easier to be wrong than it is to be right.

And there are so many ways to be wrong.

Take Discord. When I was doing a live AMA in the Phronesis Labs Discord with over 100+ members, it suddenly just decided to cut out and drop everyone from the call.

N E G A T I V E    V A L U E

I call this Feedback Loop Level 8: The Execution Guess Point.

A particularly tricky one.

When this happens, expect your customers to start looking for solutions in other places (I'm thinking about switching to Zoom).

But if it could happen to Discord, it'll probably happen to us too.

That's why we Lead With The Guess, make no assumptions, and prioritize covering as many Guess Points with tests as humanly and reasonably possible within the time frame we have.

BTW: Remember when I said that learning this stuff opens up a lot of doors for you? If you understand how to identify Value Gaps in the real world AND you learn how to put software there, there's just one thing left. Selling it.

Naval

But that's a topic for another time.

Let's press on.

2. To write the tests first, you need a testable architecture

At this point, you might be thinking:

"That's cool, Khalil - but I can always just add those tests later."

Actually, you can't.

Know what? Yeah, you can  but you're going to hate your life trying to carve out the ability to add those tests later on.

Here's why.

Ever heard of the hexagonal architecture? (Similar or comparable to the clean, onion, or ports & adapters one).

Well, the entire purpose of the hexagonal architecture is to give you the ability to reach those other Guess Points.

For example, most front-end developers don't have the baseline design foundation to write tests at Feedback Loop Level 3: The Application Guess Point.

This is an incredibly missed opportunity.

If you learn how to decouple from infrastructure here, you can:

  • force your code down various code paths using stubs
  • cleanly test side-effects using test doubles
  • have fun writing super fast, high-value developer tests that exhaust the majority of your edge cases

The thing is, unless you've started with a layered architecture, it's likely going to be a major pain to refactor towards it.

It's still possible, but it's better for you to start that way - assuming you're going to be making Guesses, because it's as they say:

Architecture is about the decisions you make at the beginning of a projectArchitecture is the stuff that matters, whatever that is.

But it's never too late.

If you want to learn this, do like we do in The Software Essentialist. Start from the innermost feedback loop levels, and work your way towards the outer ones.

There are some foundational skills you'll need to pick up along the way to get pretty good at this, like:

  • Red-Green-Refactoring
  • Programming by Wishful Thinking
  • Using the 3 forms of Subject Verification to test anything

3. Testing Requires a High Level of Mastery (But It's The Key)

Hopefully by now you're beginning to see how critical it is for us to prioritize developing the capacity to Lead With The Guess and Write The Test First.

We may not always do that if it doesn't fit into our strategy, but we definitely need the capacity to exercise a Feedback Loop at each of these Guess Points.

In actuality though, I think a huge reason why most developers don't bother with testing is because this:

It is hard to learn.

I was just chatting with one of your fellow Phronesis Labs community members about this recently.

We both agreed that in order to learn this skill properly, you need to know:

  • the basics of object design
  • dependency injection
  • dependency inversion
  • hexagonal architectures & decoupling from infrastructure
  • how to use test doubles
  • how to create great abstractions
  • how to know when your abstractions aren't great

It's true. It's traditionally been a really hard thing to learn.

It took me years to get really good at, even after having built DDDForum (see it on my GitHub) and having written the first version of SOLID BOOK.

But it's the key.

When you learn how to test properly, you learn how to:

  • Design, instead of just mixing
  • Win the game of Professional Software Development
  • Build your own SaaS products
  • Mitigate negative value in your codebase
  • Think & code backwards, producing the minimal amount of accidental complexity possible
  • Get a safe grounds to test out designs
  • Always produce the highest quality designs possible
  • Create abstractions that others love to work with
  • Develop scalable, maintainable code

    • Imagine you wanted to implement a new feature -- and all you had to do was add a few lines of code. This is what us OOP nerds call Open-Closed Principle, or extensibility for short.
  • Ultimately, you become a benefit to employers

Good stuff, y'all.

That does it for this one.

As always,

To Mastery

Khalil



Stay in touch!



View more in Testing