DEV Community

Cover image for Are Unit Tests Really Just Garbage? 💩😳

Are Unit Tests Really Just Garbage? 💩😳

Lukas Mauser on November 01, 2023

I always assumed that unit tests are just part of the job. They are just there, and it's a no-brainer to always test every new piece of code that y...
Collapse
 
ingosteinke profile image
Ingo Steinke • Edited

Interesting article with a provocative headline.

What sounds like a generalized rant against unit tests should rather be an inspiration to write better units tests, not ditch the supposedly dysfunctional existing ones.

  1. Rely on users to find bugs instead of engineers guessing them

Very interesting take, might be good in practice for edge cases - BUT a business or otherwise critical production system SHOULD be stable and tested BEFORE shipping to users!

your priority is moving fast,

This explains everything! But you should have quoted the whole motto which is "Move fast and break things" said by Mark Zuckerberg, founder of facebook and pulling the strings behind Meta.

If Zuckerberg is your role model, forget about everything. Ditch quality! Don't test your code! Use React, move fast, break things, and hope your customers will still use your products. But seriously, I'm sure even Facebook's software contains unit tests.

Consider investigating what's wrong about your existing unit tests and how they should have been written instead to boost quality AND productivity instead of making your developers shy away from refactoring.

Collapse
 
miketalbot profile image
Mike Talbot ⭐

Are you suggesting that Facebook is full of bugs? Or that it has some awful performance? Seems to have worked out pretty well for them as far as I can see.

Collapse
 
ingosteinke profile image
Ingo Steinke • Edited

Have you used React? Did you like it? Have you used Facebook? Did you like it?
But more importantly, do they really move fast and break things without testing? I don't think so. While they introduced breaking changes to React, I heard they don't update their own codebase accordingly.
But in the end, I can't tell. Luckily, I didn't have to work with React anymore recently.

Thread Thread
 
miketalbot profile image
Mike Talbot ⭐

Yes, to both and yes to both :)

For my purposes React is fine, it has foibles, what doesn't though. I think it really depends on what you are building and for what audience. My audience isn't going to notice a few more 'k in a download vs the power the product they've bought provides them. I'm sure I'd feel different if I was targeting a consumer audience with a short attention span - but the speed of releasing features and the abilities I have for separated development teams on a single product work for me.

Collapse
 
wimadev profile image
Lukas Mauser • Edited

I agree! Removing tests entirely is a fairly radical approach and certainly doesn’t work in all industries. But I like the idea of challenging these set processes that are often just taken for granted… Lot's of companies (especially in Germany I feel like) are very risk aversive even if the cost of failure is comparably low

Collapse
 
kevinluo201 profile image
Kevin Luo

Rely on users to find bugs instead of engineers guessing them

The big companies OP mentioned are "entertaining" softwares, it doesn't matter for a social media website has some bugs, or strange behaviour on Netflix interface.
For other more serious industries, like banking, retailing, medical, motor, etc., the cost of relying on users to find bugs is lawsuits 😆

Collapse
 
eljayadobe profile image
Eljay-Adobe

Unit tests are a trade-off. What are the costs of making and maintaining unit tests? If there are no unit tests, what are the costs of end-users finding bugs and fixing them? What are the soft costs between unit tests being a forcing function to embrace SOLID, WET/DRY, KISS, YAGNI principles, versus code that is rife with high coupling, low cohesion, inflexible, and hidden dependencies?

For some software, it doesn't matter if the crash rate is 5%. It may not matter that a good portion of the developer resources are spent fixing an endless and growing portfolio of bugs. End users just restart, and continue.

For other software, if the software crashes and that results in people get hurt or expensive equipment is rendered inoperative, 5% may be unacceptably high.

Collapse
 
wimadev profile image
Lukas Mauser

Totally agree here! There is no right or wrong answer for every scenario, it really depends on the software and company. Writing tests is a bit like paying for insurance. If an incident can completely ruin you, you better invest upfront, but the decision to get it for your phone is debatable...

Collapse
 
bernardigiri profile image
Bernard Igiri

The trade-off is "move fast and break things" vs take your time and build something that lasts forever. Most companies choose speed. Most users would prefer slow.

Collapse
 
tnypxl profile image
tnypxl

Unit testing is a discipline. They’re a tool to help you keep track of the assumptions and expectations you’ve assigned to the code you’re writing. The larger your code base gets, no matter how clean or simple it is, it eventually stops fitting in your head. Unit tests ensure that these expectations and assumptions are not lost.

Collapse
 
wimadev profile image
Lukas Mauser

Why not keep track of that in a spec sheet or through code comments? Much easier to write and maintain

Collapse
 
tnypxl profile image
tnypxl • Edited

Because what’s easier for you today is a nightmare for the next person trying to make changes.

Unit tests are executable and can actually validate the truth of your code. A comment nor a spec sheet will ever do that for you in any reliable away.

Collapse
 
tnypxl profile image
tnypxl • Edited

Also if its really hard to create unit tests, that says more about your code than it doesabout the process of writing tests. Unit tests should be the easiest aspect of your code base to not only write, but maintain going forward.

Collapse
 
bernardigiri profile image
Bernard Igiri

Comments are the first thing to become neglected in a fast moving software project. If no one is actively working on it, you cannot trust it's validity. Additionally, the process of testing exposes bugs that you would have missed. It also results in code that is easier to extend and maintain.

Collapse
 
kopseng profile image
Carl-Erik Kopseng

Spec sheets always get out of date. Code comments just the same. There is no syncing back after you go add that little functional change. Which ends up being 80% of the codechanges during the lifetime of the project.

Collapse
 
jonrandy profile image
Jon Randy 🎖️ • Edited

I've been a professional developer for almost 30 years, and have almost never used any automated testing, and it's never been an issue.

Collapse
 
adaptive-shield-matrix profile image
Adaptive Shield Matrix

Yeah, that totally works if you do pure UI and or integration stuff
and skip heavy logic parts.

Unit tests do not work well for that use cases.
Unit tests are there to test logic and/or state transitions (like in a state machine).

Collapse
 
jonrandy profile image
Jon Randy 🎖️ • Edited

I've done plenty of that kind of work too. Without automated testing (unit or otherwise)

Collapse
 
wimadev profile image
Lukas Mauser

Interesting. What kind of apps are you working on?

Collapse
 
jonrandy profile image
Jon Randy 🎖️ • Edited

I've worked on all kinds: desktop apps, front and back-end web stuff in a number of industries (OTA, e-commerce, fulfillment, payment gateways, image and media libraries, property management), and most recently desktop game development (UI)

Thread Thread
 
ewinslow profile image
Evan Winslow

How much were your companies spending on manual testing?

Thread Thread
 
jonrandy profile image
Jon Randy 🎖️ • Edited

No way of knowing, since it's part of the development process. How much money is spent on writing and maintaining unit tests?

Collapse
 
bernardigiri profile image
Bernard Igiri

What happened when you found a software bug? Who caught it? How long did it take to fix? How complex was your code base?

Collapse
 
jonrandy profile image
Jon Randy 🎖️ • Edited

Pretty tricky questions to answer really as I've worked for companies from tiny start-ups with very few developers - to big companies with 100s of developers... and code bases ranging from simple small libraries to large, complex systems.

I've always found that not using automated tests encourages a more hands-on familiarity with the code you are working with, and a deeper understanding of what it actually does and how it does it... better equipping you to fix and diagnose issues faster. Automated tests have always felt like an extra layer of abstraction that merely serves to slow development and maintenance... whilst also encouraging the siloisation of project knowledge (never a good thing for projects IMO)

Collapse
 
aloisseckar profile image
Alois Sečkár

I work a lot with Nuxt (a framework atop Vue.js) lately. I barely find valid cases for classic unit tests here. Often you "only" fetch data from backend and display them. Or collect data from a form and send them to backend. This can't be unit tested, this has to be E2E tested. Okay, maybe I can unit test for example getters I write in my Pinia state stores, but they are usually so straightforward that you just see the results immideately during development and once estsblished, they are quite unlikely to change. So in this case having to write dozens of dumb unit tests that just
"test" whether you can use Array.prototype.filter correctly is quite a waste of time, if you ask me.

I recently came across the concept of "visual testing" with Backstop.js - it opens your app in emulated browser, performs defined scenario (visit route, click a button, etc), takes a screenshot and stores it for future reference. If you mess something up during development, the test starts failing, becuase actuall screenshot looks different. I think this is good way for quite complex and yet easy-to-manage (because you dont have to describe the outcome) testing. On the other hand there is some overhead as you have to store the screenshots somewhere.

Collapse
 
wimadev profile image
Lukas Mauser

Very interesting approach with that screenshot testing! Thank you for sharing!

Collapse
 
devdufutur profile image
Rudy Nappée • Edited

No unit test != No automated test

I'm always more confident with integration tests and e2e tests than unit tests. Furthermore, they didn't break on refactoring. And it's always better to test actual user interaction instead of implementation details.

Manual tests are really expensive in the long term. Community tests are great but aren't applicable to any project.

Collapse
 
wimadev profile image
Lukas Mauser • Edited

That's true. There are layers to automated testing. And integration/e2e testing can give you more coverage across your system.
I can say though, that as soon as your app is just a little bit more complex and multiple people or teams are involved, e2e tests are really much harder to setup and they do require a lot of maintenance effort. You have to run and maintain a separate production like environment. And that causes tons of issues like multiple people trying to work on it at the same time, testing data being wrong or outdated, and thinking about all the underlying infrastructure stuff...

Collapse
 
devdufutur profile image
Rudy Nappée • Edited

Indeed test cases need to be rethinked.

It's about trade-offs between simplicity, side effects, replayability and maintenance but if you recreate the full test situation and delete it after the test, you can deal with those issues.

This way, you should be able to launch your e2e test on every environnent you have credentials for (no need for production-like environment, any dev or review envs will match)

For integration test, no environment is required, with test containers, or embedded databases/queues and tools like wiremock you should control you own dummy environment.

Collapse
 
miketalbot profile image
Mike Talbot ⭐

Totally with you on that.

Collapse
 
wimadev profile image
Lukas Mauser

EDIT:

Going without automated tests is not an excuse to go wild and crazy with your code. The time you gain needs to be invested into alternative failsafe mechanisms. It's like driving a sports car in race mode to make progress fast, but you better know what you are doing. It requires you to be always alert and you need to feel comfortable with running into some road bumps along the way.

Collapse
 
siy profile image
Sergiy Yevtushenko

Certainly, there are coding practices which may significantly reduce number of unit tests. But by completely ditching unit tests we increase mental overhead and feeling of uncertainty for developers. This, in turn, basically kills productivity and it gets much worse than with unit tests included. Lack of unit tests also makes many refactorings much more complicated. Refactoring in majority of cases is more time effective way to improve code than rewriting from scratch.

Collapse
 
wimadev profile image
Lukas Mauser

Yeah, guess it probably won't work for every team. You have to gather some head-through-the-wall people to pull it off.

Collapse
 
jonnyray profile image
Jonny Ray

I can see where you're coming from to a point, but I think there's something fundamental missing - it's good code that has been designed to be modular, clean, and therefore very unit testable, that you can potentially require less unit testing of. Anything less than that is usually short-sighted and doesn't consider the potential lifespan of the code and how much time you can save in the long run.

Collapse
 
wimadev profile image
Lukas Mauser • Edited

Absolutely! Going with less tests is only possible if you invest that saved effort into your code. It doesn't mean, do whatever you want...

Collapse
 
lexiebkm profile image
Alexander B.K.

"2. Manual testing
If you do need to test something, test it manually by hand. Yes, you will repeat yourself, but you are probably closer to the production environment and can easily test scenarios that might not even be testable automatically."

This is what I have always been doing. I am new to automatic unit testing, have read about how to write it. But I am always worried about time to allocate for it, instead of focusing on improving the code itself to become robust, after manual testing ( as well as manual integration testing) and rethinking over the code in accordance with the goal of the app/project.

Collapse
 
wimadev profile image
Lukas Mauser

It really depends on your project. If the stakes are comparatively low and you have a quickly evolving codebase, I think you can go very far without the need for automated testing.

Collapse
 
dsaga profile image
Dusan Petkovic

I think tests are essential for good software but maybe not a priority when starting an MVP project.

Just consider which tests to write, as some tests are not as valuable as others, and they make future change harder, because if the project keeps changing often then you need to go in and change all of the tests.

Collapse
 
jfftck profile image
jfftck • Edited

I believe that unit tests are written poorly the majority of the time -- they should test the functionality of the code, not just the happy path, but most of the time I see the failure path(s) ignored because the code coverage threshold had been met. This makes ensuring the signature of that unit less reliable and any refactor will most likely miss preserving it.

I find the idea of testing in production behind flags or certificates a better solution to the problem. You write the integration and end-to-end tests against that system with known dummy accounts, and those tests should run often enough to avoid breakages. Once a feature is passing the tests and has a level of completion to release the flag can be removed.

This could be something that a more senior developer could setup and maintain, while the business code can be done by the entire team. Having this in place would ensure that good test coverage that is aligned with the requirements.

Collapse
 
userof profile image
Matthias Wiebe

Is AI already playing a role in facilitating and improving the process of unit testing?

Collapse
 
wimadev profile image
Lukas Mauser

Copilot already does make life easier. It's going to be very interesting what's coming in the near future

Collapse
 
kopseng profile image
Carl-Erik Kopseng

Good tests are documentation. When I am to change some code, I often go straight for the unit tests and look at the overview module in IntelliJ to read all the method names. In a good system, they will tell me most of what I want to know. That's super useful when the original coder is gone, the original spec is nowhere to be found (which is the case in 95% of the places I have been), no one on the team has any idea about that feature anymore, etc.

The best unit tests are the ones that actually exercise large parts of the system and application logic without doing I/O. Pete Heard of LogicRoom calls these "Goldilock tests". You get to test 90% of your application logic with almost the same confidence you have in integration test, but they run much faster, so you can afford to test many more cases. This requires a very clean architecture though, to allow it.

Bad tests are just wasted effort: testing of getters and setters, etc. Ugh. And people need to kill tests that are duplicated by other tests. Strive to trim the fat.

Very few practice TDD, but when doing so, you often end up with better architectures and docs to boot.

Collapse
 
code42cate profile image
Jonas Scholz

but but but everything under (insert arbitrary percentage number here) test coverage is risky!

Collapse
 
wimadev profile image
Lukas Mauser

Coverage is everything 😜

Collapse
 
xoubaman profile image
Carlos Gándara

I strongly disagree with most of what is exposed in this post. Many points are contradictory, some others I would even consider them dangerous.

It's suggesting that skipping automated tests (not just the unit one, the post advocates for removing them all) just works because what we lose in safety we gain in saved effort.

Even if it's possible that under some circumstances it might be fine to skip tests, that is a (very) marginal percentage of scenarios. For each Netflix, Facebook, etc. that are where they are, there are hundreds of other companies extinct or drowning in untested codebases where changing anything is maximum risk.

Be very VERY cautious if you consciously go no-tests. It's not that easy as how is being presented here.

Collapse
 
wimadev profile image
Lukas Mauser

To clarify:

The premise of this post is not that anyone can simply skip his tests and go wild with his code. If you go down that path it requires you to focus that gained effort into careful design choices and creation of other fail safe mechanisms. If you are drowning because changing your code is "maximum risk" then clearly something went wrong along the way...

I like to compare it to driving a sports car in race mode. You make progress really fast, but you better know what you're doing when you flip that switch.

Collapse
 
xoubaman profile image
Carlos Gándara

Yet the post is written in a way that encourages jumping into Nascar without a driving license.

Collapse
 
darkterminal profile image
Imam Ali Mustofa

I am throw the product to customer, that's unit test.

I am people with no-brain, I love chaos.

Collapse
 
wimadev profile image
Lukas Mauser

Double on what works I guess 🤠

Collapse
 
darkterminal profile image
Imam Ali Mustofa

I am a Software Freestyle Engineer 🤣

Collapse
 
sethsandaru profile image
Seth Phat

Have fun refactoring things later without any test lol.

On top of that, when parts of the code change, they might have to refactor dozens of tests, no matter how well they were designed in the first place.

Single responsibility, keep that in mind. Write more small functions.

People trust a system with a proper CI/CD pipeline with testing rather than one without unit/integration tests and go YOLO on production.

Manual testing will bite you in a short amount of time, no matter what.

Collapse
 
dsaga profile image
Dusan Petkovic

Btw. I think this is crucial

"And all of this can lead to engineers becoming very shy to touch existing code that has been cemented in place by excessive unit testing. They tend to avoid rethinking existing solutions, trying out new things, and being bold in general."

Collapse
 
jacekgajek profile image
jacekgajek

Only a FE dev could write that. Unit tests saved me so much time... I could delete them after deployment, and leave integration and E2E tests, but during development they are the greatest tool to prevent bugs and document code.

Collapse
 
miketalbot profile image
Mike Talbot ⭐

Yeah, I agree that unit tests become the best way to develop back-end code before an FE exists. You've got to call it, you might as well use tests to do that.

Collapse
 
jacekgajek profile image
jacekgajek

Exactly, I had tasks when I didn't run the application single time. Especially in case of bugs - reproduce with test, fix the code, pass to QA.

Collapse
 
westial profile image
Jaume

First, I thought that the huge list of things to do as an alternative to unit testing was, in fact, part of a joke to end saying that unit testing is the faster way. But you are really convinced against unit testing.

If you have enough knowledge and experience with testing and TDD, you don't make coupled tests, or tests too hard to maintain.

There are many books to get help from about creating good tests, from Kent Beck, or James W. Grenning, to mention the best ones I've read.

Collapse
 
bernardigiri profile image
Bernard Igiri

Sounds like an excuse to write bad code. You're basically saying that testing is hard and the users will deal with your bugs for you. That's a horrible attitude. Unfortunately, large companies like FAANG can afford it. People will continue using them even when their software is bad. For those who still need to build trust with users, you do not want to copy this attitude. Test your code, the time it costs upfront will save countless hours on the back end. This is true even at FAANG, unfortunately it's much easier to hide those costs in a larger organization. The manager that finishes more projects will get the raise faster, than the one who saved the company a few hundred million in losses from software bugs.

Collapse
 
adaptive-shield-matrix profile image
Adaptive Shield Matrix • Edited

The main problem is not if unit tests are worth it but how to do unit tests the right way and then to use them at all (the right tool for the job).

The most common proponents of the anti-test movement comes from frontend devs, where mocking and integrating integrating ui libraries/components is cubersome or even painful.

If you have mocks / components -> you are not doing unit tests but component/integration tests instead.

Unit tests only use pure functions, run very fast, should test only logic and are or should be a joy to use, because you get very fast feedback if your logic function works as expected with the given data.

Collapse
 
swhinton profile image
swhinton • Edited

So if you are a startup or medium-sized company and your priority is moving fast, then you can probably get away without unit testing for longer than you think.

You don't have to listen to me or anyone else with more than 3 years of XP working at multiple companies from decades old established organizations to startups: this attitude will always lead to a software system's downfall. You are going to pay for it severely later.

Failure to write unit tests is laziness, I see it in younger engineers and old-timers on their way out who simply want to do things the way they always have. Unit tests are seen as a chore. I admit it's not glamorous, but it has saved me in the future when I made changes thinking everything is happy, only to find out that wasn't the case.

There is always a significant portion of software that you can unit test without going full "Enterprise Java". You will not write unit tests for everything because the verification requires a production environment or near simulacra (requires network, OS interface, file system, etc.) and abstracting EVERYTHING for the sake of unit testing nets minimal gains at high cost, but you would do well to automate what you can, including integration tests. My experience tells me that if you are still around after decades of manual-only testing, it's because you have cornered a niche market with no competitors (yet).

Collapse
 
rsmets profile image
Ray Smets

I have long considered observability to be far more important and impactful than unit tests.

Cool article.

Collapse
 
gulshanaggarwal profile image
Gulshan Aggarwal

I work in a startup where we are building micro saas & never introdcued units tests in our Codebase. It totally depends on your product & its customer base.

Collapse
 
kmtabish profile image
Khan M. Tabish • Edited

My thought is if your application doesn't have a good documentations then you must write the unit test cases of every functionalities.
It helps you to prevent the bugs in the dependent modules...

Collapse
 
jimeh87 profile image
Jim

I write quality unit tests so that I can refactor code safely. Code without tests is legacy code.

Collapse
 
gregorygaines profile image
Gregory Gaines

Explains why my Netflix kept crashing

Some comments have been hidden by the post's author - find out more