Like this post?
Sign up to World Class Remote, it will make you happy. Promise!
This is one for the developers out there.
Let me tell you a story.
In early 2020 I created a subscription system for a crypto token, the idea being that using a token you could set up a rolling monthly subscription to a carbon offsetting product.
The feature was just over 2,600 lines of code.
I added tests for the entire feature, this was around 1300 lines. There were 30 tests and 195 assertions.
My colleague was completing the work of integrating stripe subscriptions, using laravel cashier.
Seems fine right?
We merged our work, there was an issue, my code overrode the subscription behavior which depended on stripe payments working.
I was focused so much on my feature that I'd ignored that side of stripe, this was an oversight by myself as I hadn't used cashier before.
I had tunnel vision.
Fortunately, due to the whole testing suite for the feature, we were put at an advantage.
I knew that if the tests run the feature worked, the tests bought confidence to the code.
This enabled us to change all of the effected method names of my feature and quickly resolve the issue.
We fixed the issue in less than 2 minutes:
- Searching for all the effected method names.
- Replacing the method names with something more suitable.
- Testing between each step.
All green. All successful.
This issue was resolved on a pair programming video call, on my colleague's development machine, I am based in the UK they are based in Bulgaria.
The developer I was working with wasn't as well versed with testing as myself it was a great experience for them to feel the benefit of the time savings.
Without these tests, it could have taken hours to update the name and manually retest the whole feature. Even then our confidence would have taken a hit.
That is why you should test. It will save you time, your client money and will uncover issues that you have probably missed.
Trade hours for minutes.
It is tricky though, at first glance, and with a short term view of testing seems expensive especially with legacy systems. From the outside view, it first seems the benefit is opaque.
Software development is complicated, there is a myriad of solutions for a problem let along with different stylistic differences between developers.
With little planning, most of the time the catchphrase for difficulty and options is "It Depends...".
But that doesn't help you or your client.
If budget or time is tight I opt for this approach.
HTTP API integration testing combined with asserting the database state.
- Mock the expected experience of a client using your service, using API calls.
- Assert that the response is correct and conforms to the spec.
- Assert the state of the database, after the API call from inside of the integration test.
Aim to get into a position where if you comment out one line of code it will break the tests.
I can imagine that many of my tests break the concept of single responsibility and that it could be recommended to split them down further, but I don't care.
Sometimes it doesn't make sense to break down everything into how we "should" design our systems and write our code, sometimes doing that can be a waste of time, it doesn't instantly make your product better.
When budget and time is tight, we need to make difficult decisions and move forward with our gut. Sometimes we'll make mistakes.
Sometimes it is helpful if you think of testing as exploratory design, we are all used to writing notes to plan and remind us of our next steps. Think of the act of writing tests as permanently storing your notes, your process.
Testing is a form of documentation, for new developers to understand how your feature works. If all of your tests run, they can be used as a source of truth.
Reach out to me.