The other day I was talking to a guy about a possible freelancing gig
and he said how wonderful it was that I should bring up the topic of
unit/automated testing without being asked. He said that most (many?) developers don’t have the level of rigor to use automated testing.

My reaction was one of disbelief “Rigor!? But automated testing is one of the laziest things a developer can do! It speeds stuff up so much!”

As luck would have it, last night I was hit over the head with my own words and nearly died debugging a single function.

I was working on Stripe webhooks and for security reasons decided not
to use the event data sent in request body. Makes sense right? Take the
event id from request body, then fetch the actual event from Stripe.

It’s the only way to be certain you aren’t responding to bogus events
sent by an evil person trying to make you look bad (nothing actually bad can happen, at worst a customer would get extra paid invoice emails).

Due to poor decoupling – I didn’t really want to decouple a 6 line
function into two functions – everything was now difficult to test. I
can’t create events on Stripe’s servers with unit tests and without actual events existing I can’t test the function works as it’s supposed to.

How many bugs can you put in a 6 line function anyway?

A lot of bugs!

When the client tested on staging … it didn’t work. Invoice email wasn’t sent and Stripe complained of a 500 error.

It took me almost two hours to fix all the bugs because my testing cycle looked like this:

change code

commit to develop branch

switch to staging branch

merge develop branch into staging

push to github

change to other terminal window

pull from staging branch

restart python processes

go to Stripe dashboard

pick customer

create invoice item

create actual invoice

choose invoice

pay invoice

go to Stripe logs

find invoice.payment_succeeded webhook

scroll down to response

look through raw html of django’s error page

find symptom

GOTO 1.

That’s right, a whopping 20 step debug cycle all because I’m
an idiot and couldn’t find a way to automate this. Or maybe I was too
tired to do the unobvious thing … although I still don’t want to split a
6 liner into two functions.

Yes, all of those could easily have been caught if my test coverage
was actually any good! And then not only would I not look like an idiot
in front of the client, I’d probably spend no more than ten minutes
fixing this.