DEV Community

Cover image for Why do great developers love writing tests?
anabella
anabella

Posted on • Updated on

Why do great developers love writing tests?

This article was originally published in Typeform's Engineering Blog

Part one: OMG I'm totally buggin!

I’ve been hearing about the importance of writing tests for years. No wonder, since during all that time I was working as a QA Engineer within a team of developers. I’ve heard about how important unit and integration testing is, the wonders of TDD, code coverage, you name it.

Agile teams and organisations kept talking about it, and for a long time I assumed it wasn’t related to my job. Even though it had the word “test” in it, it wasn’t the kind of testing I was involved with. So I just wrote it down in my mental “Book of Things That Are Good Things” and hoped that one day I’d grasp the reasons why it belonged there. I was clueless.

In the meantime, all those years ago, I was learning to code. I wanted to switch my career to development, or at least test automation. Sites like Codecademy were just getting started back then and I was going crazy with their free courses. Somehow it never caught my attention how the exercises knew when my code was incorrect, how come they usually had a pretty good idea of what part of it was off target.

After that, I did some more intense “classroom coding-courses”. There, I learned a little bit about the purpose of unit tests. They test every functional cell (or unit) of the code to make sure it does all that it is suppose to. Now, after letting this new definition sit in my head for years without giving it a second thought, I realised something new:

Unit tests don’t test outward facing features –like a login form or an endpoint– they test the inward facing functionality, making sure a piece of code can be properly used by other pieces of code.

Since I was learning some new tricks I was also starting to create small pet projects, either to apply what I learned or to challenge it by building something fun that I came up with. There were a lot of tedious sides to this: obsessively googling for solutions, not using git, figuring out what CORS is… you know how it is. But one of the worst things about my process (or lack thereof) was having to test every single use and edge case on every single change that I made.

If you’ve read this far, you probably know what I’m talking about. Either you’re experiencing it right now, or you remember it from when you were starting to develop real, working things. There’s no way of forgetting that tedious feeling of having to manually test every single flow variant each time you introduced a change in the logic. Or, worse, discovering a broken flow after a 3-hour-long refactor and not having a clue of when it had stopped working.

Now imagine a situation where all of that is covered by just running a command on the terminal, and watching a sea of green (and occasionally red) text unfold. Wouldn’t that be lovely? It definitely would, but somehow it still escaped my understanding. My projects are not “real applications”, I thought, they don’t need tests.


"2001: A Space Odyssey"

Part two: The end of my bone-as-a-weapon days

I’ve been working at Typeform for a about 6 months now. I’m part of a team that is very self-sufficient testing-wise and they don’t really need me to keep the QA hat on at all times. We do a lot of mob and pair programming and I get to take part in the development of features, changes, and fixes. I’m learning a lot with this experiences, but there’s one thing that always surprises me: when we finish a task, my teammates immediately want to write tests for it. It feels almost as if it were an impulse or an unconscious reflex, not something they remember they have to do. And somehow they always catch me off guard.

At those moments, I’m inclined to feel happy and relaxed. The fact is we’re done understanding the problem, discussing approaches and sorting obstacles, and finally got the thing working. I just wanna take a quick coffee break, but all they want to do is make sure everything is covered with tests.

And it’s only today, after almost 9 years working in the software industry, that I understood why:

These people care about code, and not only the code they write themselves. They care that it’s readable and maintainable, that it follows good standards, that it’s efficient and that it does everything it’s supposed to do, both inwards and outwards.

But, they work on real-world codebases, which tend to have a lot of code, in a lot of files, for a lot of features. And there’s only 24 hours in a day. They need a reliable and fast way to ensure that their change works and — most importantly — that everything else still works too.

Great developers love writing tests because they care about the code, and they know that (well-written) tests are the only reliable way they can feel more confident that it works.

They also know that if it doesn’t get tested when it’s fresh out of the dev oven, it probably never will. This is also why things like Test Driven Development (TDD) exist.

When you use a TDD approach, you start by writing tests for everything that you need to add or change. Yes, I’m serious. Write the test before you write the actual code. All the new tests will fail, of course, but then you write your code so that they all pass. You start by having coverage, then build the thing that you need to cover.

TDD has an additional value: focus. Only code that makes the tests go green should get written.


"Shawshank Redemption"

Epilogue: I hope the tests are as green as they have been in my dreams

My final point here is not to brag about getting to work side-by-side with great devs, but rather encouraging you to get acquainted with testing your own code sooner rather than later. Make it a necessary thing in your process. Not because it’s an industry standard, a good practice, or because somebody said you had to. Simply because it will no doubt make your life as a developer easier and happier.

An please don’t be like me, some things are too obvious to take years to put together 😉

Top comments (38)

Collapse
 
quii profile image
Chris James • Edited

All excellent points.

I've worked in a few environments, some with tests some without. Some of them were even huge systems that had no unit tests.

The people working there were so smart, so very clever. They had to be to keep it all working. I couldn't really take it, it was just too taxing for me.

For me it's a matter of scale. Tests let me work on big complicated systems because they document how a system works and gives me freedom to play with specific areas of the system without fear of breaking them. Plus I don't have to understand the whole system in order to make changes.

Working in a TDD manner I almost describe it as "dreamy". You just break down the problem into small tasks (imo, this is the #1 skill a software developer needs to learn) and then gradually iterate, writing tests for more requirements and refactoring slowly and surely with minimal stress.

It's why I work hard on this quii.gitbook.io/learn-go-with-tests/ because i 100% believe that TDD is an enabler of high quality, less stressful software development

It's why I advocate for releasing on fridays too dev.to/quii/why-you-should-deploy-...

Collapse
 
anabella profile image
anabella

I've been meaning to learn go so I can join the backenders mob programmings (and actually follow along).

This might be a sign from destiny.

Collapse
 
quii profile image
Chris James

Yes!

Go is a lovely language to start with it too because it's all built in.

Do let me know if you give it a go (pun intended) and I live for feedback.

Better still, contributions very welcome

Thread Thread
 
anabella profile image
anabella

Will do!

Collapse
 
bdmbdsm profile image
Bohdan Dmytriv

Agree with you!
Few months ago I've make a presentation about TDD and described it as some practice that delivers us up from loosing concentraction ind fear of unknown bugs. So I felt that many people have wrong impression about testing, like "tests consume a lot of time", "tests aren't code: they're not bring functionality", etc. After my explanations & examples they changed their minds on tests. That's why I'm concern: there's a need to bring this knowledge to the people.
Thank you!

Collapse
 
bgadrian profile image
Adrian B.G.

But, they work on real-world codebases, which tend to have a lot of code, in a lot of files, for a lot of features.

"and bugs, and anti patterns, and bad code, and monoliths", which all can be fixed anytime if you have tests!

Also they are good for documentation, you can understand what the code suppose to do, even if it has the worst naming conventions and you do not know the language!

For me the biggest advantage is the ability to refactor without having to prey before the release! This transforms a code from a brick to a jelly bear, flexible, it can be bent to accept new features.

jelly

Collapse
 
anabella profile image
anabella

I like the idea of tests as documentation. I have experienced it first hand, going to the tests (unfortunately as a last resort) to try to figure out how something works, but I didn't think of it for this text.

Btw, you made me think of a brick of jelly bears... a catastrophe that can sort of work as a metaphor for some codebases out there 😅

Collapse
 
bgadrian profile image
Adrian B.G.

I admit, it wasn't the best metaphor I've made up :D

Btw, my comment comes after an extensive experience on legacy code with 0 automatic tests. I've seen the ups and downs of monoliths, the pros and cons, and one thing is for sure, once you go tests you don't go back. They are not a silver bullet, they just make our life easier.

Collapse
 
jonrandy profile image
Jon Randy 🎖️ • Edited

I've been a professional developer for 23 years and have never used automated testing in any projects. I've had a go at working in this way and just find that writing the tests slows me down and ruins my coding flow. For me, I feel it adds an unnecessary overhead to development

Collapse
 
jako profile image
Simone

Hi Jon, I totally understand your comment. I've been a developer for more than 30 years; now It's just 10 years I'm into testing.
It was so difficult at first, I could see only a black mess without meaning and without form. But I was stubborn and went to a course to learn in practice.
Now I don't use tests on 100% of the project, but I know that some parts are easier to develop and maintain with tests than without.
To get there I needed a very big mental shift.

Collapse
 
anabella profile image
anabella • Edited

Hey Jon! I know in Software engineering we usually accept a lot of things as "revealed truth" and maybe never question them as long as they serve our purpose. I have found testing things thorough automation to be a revealed truth because it helped me work in what I feel is a better way.

And so, I'm curious about some aspects of your workflow, if you don't mind:

  • First of all, what sort of technology do you work with (I mean languages, fwks, etc)?
  • Do you work in a team/s? Or have you?
  • How do you make sure everything works after new features or refactors (big and small)?
  • Do you use/need continuous deployment or integration? If so, how do you ensure that newly deployed/merged code is not breaking any of the old things?
  • do any of these things, if not done by tests, take up a considerable amount of Time?

Just in case: I'm not trying to find a way to prove I'm right, I'm just curious about your context and workflow.

Collapse
 
jonrandy profile image
Jon Randy 🎖️

Technologies I work with:

  • Through most of my web development experience (I've built desktop apps for windows too - Visual Basic back in the day) I have worked with PHP, JS, HTML CSS. In recent years I have also worked with node.js and Ruby. Current projects I am involved with utilise PHP, Ruby, and JS.

Working in teams:

  • I have worked solo and as part of teams large and small. Everything from building my own frameworks from scratch and using them for freelance work; to planning and architecting a large project, hiring my own team, running the project as a lead developer; and working in teams responsible for smaller parts of very large websites. In recent years I have been in larger companies, and have responsibility for a number of smaller projects which I work on mostly solo.

How to make sure everything works?

  • Continuously (manually) testing my work whilst in development, being sure to test all areas that the changed code affects. I'm usually fairly confident that a refactored function will work before I run it (I kind of run code in my head - others do this too, surely?) and usually I find the main reason it doesn't is simply typos. Admittedly the languages I work with allow for very quick changes and re-tests (i.e. no compilation)

Using CI:

  • Yes, at the last few jobs I have had we use CI. Everything is tested again (manually) in a staging environment before going live (a number of people test at this point, and only when all are happy is it pushed to production). I should point out that this is only the projects I have been involved with. Other projects within the organisations have had automated testing, but not all

Testing taking a considerable amount of time:

  • During my development, I would say no, but again as I pointed out - I work with technologies that lend themselves well to a fast change/test process. As for others testing at the staging environment - they are essentially just checking from an end user point of view making sure all functionality is working. I couldn't speak for them as to whether testing slows them down.
Collapse
 
quii profile image
Chris James

Have a read of this

geepawhill.org/tdd-and-the-lump-of...

What do you think?

Collapse
 
jonrandy profile image
Jon Randy 🎖️

Reads pretty much the same as most articles promoting TDD. To me, it doesn't really reflect the reality of development (at least the way I do it). While I'm coding, ideas come to me thick and fast and I will often do a total u-turn on how a function is implemented or have a complete change of heart on how a large problem should be solved. The whole process is very fluid and organic - taking place in one place - without jumping 'out of the code'. Having to keep leaping out of that flow really does not work for me and I feel ends up with an inferior end result that took longer to produce.

I'm not sure if the way I learned to code has anything to do with my methods - quite possibly I guess as I am totally self taught - from the age of 7. I have no formal qualifications or training as a programmer - just 35 years of experience (about 23 professionally)

Thread Thread
 
aabhina profile image
AA

To add to this healthy discussion, this 3 part hangout series video is pretty good as well.
Lots of pros & cons perspective from 3 of the top many names in the software industry today.

youtube.com/watch?v=z9quxZsLcfo

Collapse
 
epogrebnyak profile image
Evgeny Pogrebnyak

My selling point for tests is refacting. If you cannot tests something easily (eg your setup/fixtures grow too big, you are inclined to use mocks and generally testing is problematic) - you have bad code, or worse some bad design/architecture decisions, the tests reveal that.Important and more rare skill is knowing what to test, and achiving meaningful coverage with fewer tests. The tests are never complete, cannot tests everything and under all coditions,it is becoming very exensive, so picking the risky parts of code for tests is super important.

Collapse
 
gerchog profile image
Germán González

Excellent post.

Where can I start? I know there are several testing tools, Mocha, Jasmine, Karma. What do you recommend?

Thanks!

Collapse
 
4lch4 profile image
Devin W. Leaman • Edited

If you're working with Node.js, I use Jest in my tests and it's pretty wonderful to use. I highly recommend giving it a shot 😊

P.S. Here's the Getting Started guide I followed when I first gave Jest a shot.

Collapse
 
gerchog profile image
Germán González

Jajaja I forgot to explain what language I use. Currently I'm working with C # for the backend and Angular for the front.

Thread Thread
 
4lch4 profile image
Devin W. Leaman

I've honestly never worked with either of those so I'm not too sure what your best option would be 😅

Hopefully, someone else can chime in shortly with some help though.

Thread Thread
 
darksmile92 profile image
Robin Kretzschmar

Thanks for the clarification, maybe you can edit your post to get this info straight at the first glance? :)

Collapse
 
anabella profile image
anabella

Hey! Thank you for your comment :)

I think there's 2 sides to this. First and most importantly I would devote some time into researching what and how to test your code. This is important and won't change much with tech stacks.

On the other hand, there's how to test with your current stack. I read it's C# and Angular. Maybe the best is to start by covering your backend logic, which should be more stable I guess. Look for a tutorial about unit testing in C# (of which I know very little) just follow it and then try to adapt it to your own needs. The tutorial should give you some idea of what and how you should test too. Start by the most critical areas of your app and move into more secondary features/code.

I hope that helps. Sorry I can't give more specific advice. Happy testing!!!

Collapse
 
juanfrank77 profile image
Juan F Gonzalez

From all my years of developing in C and then in Java, they never taught me how to write tests in college (actually, once a teacher wanted to show JUnit and it was a Huge mess).
So now my question is more like, how do one learns to do TDD in JavaScript? with all the bunch of testing frameworks out there.

Collapse
 
aabhina profile image
AA

A very good introduction to doing TDD with JS is this book by Venkat.
It is an absolute piece of beauty, must read for all developers.

Test-Driving JavaScript Applications
pragprog.com/book/vsjavas/test-dri...

Collapse
 
anabella profile image
anabella

I know college courses rarely touch the subject, as they rarely touch many aspects of real-life / industry software development.

About js, I think it's the same as with other aspects of the ecosystem: it's not about the framework, it's about what you do with it. The fw should be only a medium, a helper to get there.

If you're really lost about where to start, there's always tutorials about the hottest and latest fw/library (even for testing). Pick one and try to apply it to your applications. If you see value in it, and it becomes a habit, you'll be able to translate it into any other fw that comes along.

Fwks should be approaches to the solutions: if you know the problem well enough then you can choose which one suits you best.

Collapse
 
juanfrank77 profile image
Juan F Gonzalez

Awesome advice, thanks for sharing :)

Collapse
 
robdwaller profile image
Rob Waller

A nice post explaining your journey which I imagine will be very useful for junior developers to read.

One minor edit to one of your quotes would be:

Great developers love writing tests because they care about the code, and they know that (well-written) tests are the only reliable way they can be more confident that it works.

Even with tests you should be suspicious of your code :)

Collapse
 
anabella profile image
anabella

As one of my great co-workers would say "you are correct".

You can never "rest assured" of anything, really. It sounds like blind faith. There's always many implications in every feature or change, and even if you think you've covered everything, you can never be 100% sure.

Thanks for the feedback :D

Collapse
 
alanmbarr profile image
Alan Barr

Products change and maintainers change. These things exist for people and keeping a record of what people like or want in their software is challenging. Not only maintaining correctness but also joy. Applications rise and fall. I remember enjoying winamp and iTunes for a time. As a user I can tell when quality is being skimped or features are being packed in. I like tdd for quick feedback and hope we can find more ways to build in mechanisms into our software to make better products for people.

Collapse
 
cyberhck profile image
Nishchal Gautam

For me, I just find it fun to do so, specially with tdd, it's fun, and I actually find it quicker to develop, I have my tdd setup which makes me very quick, I never leave the ide

Collapse
 
ben profile image
Ben Halpern

I'm already recommending this one 😄

Collapse
 
anabella profile image
anabella

So honored to hear you liked it, @ben . Thank you and thanks for sharing :D

On a personal note I wanna take the chance to thank you for this platform and for your inspiring devotion to make it great every day <3

Collapse
 
ben profile image
Ben Halpern

Thanks!!! You're 2 for 2 on absolutely delivering gold stuff for the community. So THANK YOU!

Collapse
 
ben profile image
Ben Halpern

Looks like we have some bugs when it comes to multi-level liquid tag embeds. 🙃

cc: @maestromac

Collapse
 
anabella profile image
anabella

You can call them bugs or you can call them generative art. Up to you.

Collapse
 
alanmbarr profile image
Alan Barr

hardest working people in the business

Collapse
 
develcuy profile image
Fernando develCuy

Now I'm very curious about testing tests. It always sounded to me like the chain rule of calculus' derivatives.

Collapse
 
anabella profile image
anabella

I don't know much about calculus, but I do always "test" my tests (at least the first ones while I'm still setting things up) to make sure they're not just going green in any circumstance 😅