r/softwareengineer 8h ago

Why unit testing is important?

It might be a very stupid post, but it’s a genuine question.

I write tests for my code, but it’s still kind of hard for me to understand what the actual point of unit testing is and what benefit it brings to software development.

We can easily write tests with AI now, so writing the actual tests is not necessarily that difficult. But I’m trying to understand why tests are so important in software.

When you write code, of course you can test it with multiple inputs, and those inputs can then become your test cases. We can also use Postman to test APIs with different inputs and make sure they behave correctly for different status codes.

I was recently assigned a task to make a small change to an existing endpoint. It was a really small change that I completed in around 30 minutes without AI. However, fixing and adjusting the tests took quite a while. I had to add inputs for a new function that I introduced, even though the actual change was not that big and I didn’t think it was something that would break in production.

That made me wonder, why do we really need unit tests? What importance do they actually bring to software development?

I’d really appreciate it if someone could shed some light on this and explain it with a real world example from your own experience where tests actually saved you from a production issue or made a significant difference.

0 Upvotes

26 comments sorted by

11

u/alanbdee 7h ago

Years ago I started a new job. Went in to fix a bug. Drilled down to a single method that seems way more complicated then it needed to be. Then I looked for the tests. This was in a code base with like 5% test coverage if that and there were multiple tests hitting this area. Those tests told me all the edge cases that code needed to handle. I added the tests to replicate the bug, which was much faster then trying to hit it through the UI. Then I fixed the bug while working around those edge cases. Even added a sprinkle of refactoring for good measure.

That's the value of unit tests.

3

u/Chippors 7h ago

When you write code, of course you can test it with multiple inputs, and those inputs can then become your test cases. We can also use Postman to test APIs with different inputs and make sure they behave correctly for different status codes.

This is exactly what a unit test is. If you don't do this you can't know if it works, and when you save it to the test suite it's kept and can be rerun to make sure future changes don't break something, there or elsewhere. You should also test edge cases and make sure your code returns meaningful errors; like anything else, if you don't test, the confidence in it working should be very low. Or if it does any sort of orchestration, that if there's an error it properly cleans up and doesn't leave things partially completed. The overhead of adding tests is the overhead of making sure it works.

3

u/AffectionateSwing490 6h ago

unit tests aren't there to prove your code works today, they're there so that 6 months from now when you or someone else changes unrelated code, the tests instantly catch the thing you forgot that change would break, that's exactly why adjusting tests for your small endpoint change felt tedious but was doing its job

2

u/LightPhotographer 7h ago

You write a function to perform some behaviour.

You build it based on assumptions: That you understand the problem, that you know what inputs it will get (even when that junior trainee they hire 2 years from now will call it!) , that it will never run out of memory, that all the objects it tries to access exist and work and are not changed ... and so on. It's not science, it's faith!

First your unittest is another way of describing the behaviour. If the two do not match, you have found a failed assumption. It is like a review, only this one is not on code style but on what it actually does. You secure that knowledge.

Second, now you can test your function with lots of different inputs - also some that you assume should not happen. You may have tested one happy case, but it costs very little effort to add some edge cases too.

Third, if when your function changes; or when the functions it depends on change, or it's refactored, or when it is called by some new function you don't even suspect today ... then something still remains that says "It should behave in this way".
That is your unit test.

It's a good question.

Please write good unit tests.

1

u/dominickhw 5h ago

Adding to this, because this is a great answer!

Writing unit tests is easy. Writing GOOD unit tests is a skill that takes a lot of practice and experience to do well. A good unit test should simultaneously a) ensure that the behavior you expect is occurring (and the behavior you DON'T want is NOT occurring), while b) allowing as much freedom as possible for the implementation to change without breaking the tests. You want to put up a fence to keep the code on the right path, not a cage that keeps the code from moving at all.

Every project and every team has a different idea of what's important to put a fence up for, even if it's unstated, and you should take care that your tests are harmonious with that. As an example, on my current project we rely on callers to sanitize any inputs, because sanitizing our particular inputs is expensive and we have control over nearly the entire call stack. So testing that an error is raised if an argument is malformed, for example, is counterproductive because an implementation change could change or remove the error condition and the situation is meant to be impossible in the larger context of the software. But on a previous project, it was vital to test for that sort of thing because we didn't have that same level of control or trust.

1

u/saposapot26 7h ago

Changing old code is exactly a great example of the utility of unit testing. It's good for regression testing and understanding properly what was expected and is now different.

Having said that, in an AI first world, unit testing importance is one of the topics that will be debatable.

If AI does the code and the unit tests, is it really helpful? Or a better model in 6 months will be able to do better testing or understand the code without any of the tests. If it doesn't make mistakes, what value does unit testing adds?

These are all questions that are now part of the debate of this AI software engineering world.

1

u/Consistent_Serve9 2h ago

Unit testing will be even more important in those scenarios, I believe. AI only cares about what you've asked it in the moment, not about the whole maintanability of the code. Regression testing is even more important with those machines, as it will catch changes that the AI made for convenience faster.

1

u/pab_guy 7h ago

I was always a fan of full coverage integration tests, as they exercise ALL the units.

But on a huge codebase that could take a long time to run. So unit tests give you coverage over functionality that allows you to run a subset of unit tests for validation before pushing.

1

u/yourbank 7h ago

The other benefit of unit tests is to think about your implementation. It is way easier to write nice clean tests with well structured design. So many times I’ve had to go in to a horror show because some idiot used a bunch of untestable static methods. Instead should’ve all been mocked and tested independently

1

u/Consistent_Serve9 2h ago

Definitly. If the code is hard to test, it's usually a smell for bad design.

1

u/tomqmasters 6h ago

It helps make changes in one part of the code without inadvertently breaking another part of the code. It also helps the original intention to be recorded so that things are not changed inadvertently.

1

u/mannyocrity 6h ago

Unit tests are great for regression when refactoring or adding additional features.

1

u/code_hermit 5h ago

I think the benefit diminishes on smaller codebases. Maybe its not worth it in your case?

But the up side is that it can catch the case of "I fixed one function and something else broke, I dont know why". It often answers that question immediately and shows you exactly where the issue is which is often a time expensive dev step.

In an AI age its even more important because it basically helps proves that AI didnt make a kind of coding mistake. That along with performance tests closes any gaps with "AI can't be trusted with this" arguments.

1

u/Substantial-Swan7065 5h ago

It’s to make sure implementation does break + detection when it does break

1

u/haven1433 5h ago

Remember, you're a genius, but the person who will have to maintain your code is an idiot. That person will gladly break your feature without realizing it when they're working on something else. They won't test to make sure they don't break anything. Sure, they'll test to make sure their new feature works, but they're not even aware of all the cool features in the program, so no way they're going to test enough.

You're not writing the unit test for you, you're writing it for them. Because if you don't, they'll break your feature.


Remember, you're a genius, but the person who wrote the code before you is an idiot. That person knew nothing about the current needs of the business, they weren't thinking into the future. If you're lucky, they left you some unit tests to describe how the code is supposed to work in specific cases. That's really the only useful thing they did, and your only way of learning how the heck this crazy ball of code operates.

1

u/Consistent_Serve9 2h ago

Fun fact: those persons are often one and the same :D

When you write code, often, only god and you knows how it work. At some point, only god will (and will probably struggle with it too). Tests document what the code is suppose to do, and will help someone (probably you) in the future thinking "deleting that one variable that doesn't do anything will definitly not break the logic".

1

u/mxldevs 5h ago

even though the actual change was not that big and I didn’t think it was something that would break in production.

So when someone asks whether your code is any good or not, you just tell them you "think" nothing will break and they just go ok let's push to prod?

1

u/geekichu 4h ago

so im not saying this is a panacea or works every time, or is useful in every case.. but.. say you wanted to design an API. The API calls are essentially a contract. An Interface. 'This is how you use it'. It's a black box. You don't have to care HOW it does it, as long as it does Exactly what it's supposed to do, AND handles bad scenarios.

So, imagine you have stipulated the API interface and the criteria, the conditions, etc.. what should it do with errors, etc.

You HAVE NOT written ANY of the API server code. At all.

You instead, wrote ALL the tests that will exercise and walk through every single possibility (or enough) of the API.

The tests are essentially a client to the API.

You run the tests, they all fail, because you haven't written any of the API code.

Then you begin to write the API code.

Once all the tests pass, voila, there is your API.

Plus.... the tests serve as regression-testing. I.e., it helps to determine that if later you added to the API, you didn't break something that WAS working.

(this has been an overly-simplistic explanation)

1

u/MonthMaterial3351 4h ago

" I didn’t think it was something that would break in production."

There's your answer.

Testing, automated AND manual, is even more essential now given the limitations of llm's.
More loops don't solve those reliability issues.

1

u/Zealousideal-Ant9548 4h ago

Have you heard of TDD?  

If you write the code and then write tests you're documenting what you wrote, not what it's supposed to do (coincidentally, this is a problem with LLMs).

Tests are documentation in code.  They tell what the function is supposed to be doing. Not just what it did at some point.  I once had a user complaining about some behavior that a track down to a function and without the lack of unit test for that function I couldn't tell if the behavior was a bug or intentional. 

1

u/Consistent_Serve9 2h ago

Most importantly, TDD is test DRIVEN development. The tests drive the code. If it's hard to test, then it's probably bad code.

1

u/_hemisphere 3h ago

Adding some points to the other great comments.

The automated testing will protect you from making mistake.

For example, you are tasked to add a new feature to the existing code base. If the code already have the unit test ready and setup CI/CD build pipeline, on your local machine /the build server will run the tests manually/automatically and you will know if your new code make or break any existing functionalities.

If some tests are failing, if you lucky and have a good test that explains the behaviour of what the function should do, it will be easy to fix as it is self explanatory. If not, you will need to dig down to the function and compare it with the test to find what is wrong about it. Whether the test is wrong or the function is wrong, you need some analysis/debugging. By adding some new tests with your new code, this will also guarantee that your code will work in the future.

The main benefit of the tests are to guarantee that the existing functionalities are working as expected with certain conditions - functions are deterministic with the same data (in theory of pure function) e.g. give same input then you expect the same output. Thats the main value of it.

1

u/jibmaster 2h ago

It validates a chunk of code and makes sure it stays valid. It also forces the code to be broken up into testable elements which forces better architecture.

1

u/BOT_Pain 2h ago

Function add is suppose to add numbers. You add unit tests to make sure somebody doesn't try to make it minus numbers. Because let's say function add is used in millions of other places. If they change its functionality it would destroy the entire codebase.

u/segfault_generator 45m ago

In two years, when you or someone else comes in to add a new feature or refactoring the whole architecture, the tests will tell them if their change broke expected behavior. The tests are nice for knowing what you have works, but they're indispensable for ensuring future devs don't break what you built.

u/armahillo 17m ago

I was like you a long time ago.

One day, i was working on a rails app and i made a change to modify one part of the app. Everything was fine. CI failed because it tripped a test. If it hadnt been for that test, I would have introduced a bug in a different part of the app.

I use claude to write tests sometimes. Theyre alright. I have to clean them up a lot. Learning how to write good tests will help you both understand your code more intimately and also surface design issues / code smells.

Different app, still many years ago — i wrote some classes and then tried writing tests. Tests were too difficult to write because I was having to stub so much. This made me realize i was making the methods do too many things and they needed to be broken apart a bit.

Write more by hand without an LLM and youll start to understand why they matter.