DEV Community

Cover image for Should you ALWAYS write unit tests?
Alan Barr
Alan Barr

Posted on

Should you ALWAYS write unit tests?

I was reading an article about unit tests. Honestly, it seems like a lot of effort. Do you receive a lot of value from your unit tests? Personally, I'm still trying to understand domain-driven design. I feel like with supple design, we need to use several techniques to pin software on the wall. Constraints such as revealing interfaces, side-effects-free functions, and many assertions should make your software better.

What do you think? Is it always better to write unit tests?

Top comments (15)

Collapse
 
ben profile image
Ben Halpern

There is definitely a whole rarely write unit tests crowd.

I think some of this depends on the quality and reliability of the tools you have at your disposal to test at different layers. If my tools for integration/system testing are robust and reliable, I probably use more of those.

I sometimes think that is lost. Unit testing is usually pretty straightforward, but higher level tests might give you more bang for the buck but could be either more or less reliable depending on how you wield the tool.

Collapse
 
pauljlucas profile image
Paul J. Lucas

Honestly, it seems like a lot of effort.

Yeah, well, that's part of being a software developer. If someone thinks unit tests are too much trouble, perhaps there are other careers to which they might be better suited.

The more complicated a system, the more you need unit tests. If a developer hates writing unit tests, it can be a sign of laziness, arrogance, or naivete (or all three).

... we need to use several techniques to pin software on the wall.

I have no idea what "pinning software to a wall" means, but nobody who advocates for unit tests advocates only for unit tests.

Constraints such as revealing interfaces, side-effects-free functions, and many assertions should make your software better.

I have no idea what "revealing interfaces" means, but all the rest are good in addition to unit tests.

Collapse
 
alanmbarr profile image
Alan Barr

You are right, I should have mentioned that I am reading the book Domain-Driven Design and I'm trying to understand what it all means. I will mention that next time 😊.

Collapse
 
aregtech profile image
Artak Avetyan

It all depends on the goal you want to achieve and the software you write. If you are developing a framework, I think unit tests are good, because you can test the APIs of your objects as well as demonstrate the use. If you develop an application, maybe make sense integration and/or functional tests, where you can create more complex cases with various data to test modules from top to bottom. It would as well help to optimize the codes.

I develop a framework with tools. Recently I've written about a story of a bug, which first occasionally discovered at GitHub action workflow then fixed with the help of unit test because:

  • Bug appeared only at GitHub (shortly, it doesn't have timezone)
  • Debugging on GitHub is impossible
  • No logs were available.

To identify and fix the bug, unit tests helped a lot.

Collapse
 
balastrong profile image
Leonardo Montini

ALWAYS is as bad as NEVER, advice with these words should usually be taken with a pinch of salt (notice I said usually, and not always 😄)

If you have a really valid reason to not write them on a specific project that's ok, but I would keep the default as "yes, please write them".

Collapse
 
christopherzhong profile image
Christopher Zhong

Writing tests is a way to validate that the code performs according to specifications.

Let's take something as simple as writing tests for DTOs (data transfer objects). Suppose you have a field that must be a UUID, and there is a line of code that validates the value is a UUID. Removing or changing that line should cause at least one test to fail.

This is a straightforward test. It is more effective to validate this using unit tests than either integration or end-to-end tests. This is because the unit tests can be in the order of 10s of milliseconds versus the integration / end-to-end tests that can be in the order of 100s of milliseconds or longer.

Collapse
 
cwprogram profile image
Chris White

If you're not working with a team, the value of unit tests and other types of testing can be difficult to see in some cases. The reality is it's a slight form of code duplication. Once you're in a team though where you're not sure of the impact of your code to everyone else's, that's when testing shines. Having test pass before PRs helps prevent a lot of back and forth because it get marked request changes for something a test could have easily caught. It's especially useful in cases where one change may affect the code path of ten other places (that might not have even been written by you).

In general when I work on projects first there's a PoC/discovery phase. This part of a project doesn't really work well with testing since I'm not sure if some library I'm thinking might work actually does what I need it to. Once I have a good idea of how the code works is when I start to pull in the testing.

One issue with developers and tests in a work environment is they don't get properly added to the original estimates. When deadlines get to a certain point, there's no turning back and you may struggle to fit tests in.

Collapse
 
d_inventor profile image
Dennis

Unit testing has never been a very big thing in my company. What I find is that the people in my environment have a "practical mindset" most of the time. Things that I hear and see a lot in my environment are things like: "Why would I use a strategy pattern here if I can also use a simple switch-case" or "Why would I use separate models here if the model that I have already has all the data I need". There's this thought that we need to get things done now and if it works, then it's good enough.

I think unit testing is very important, but even if you don't actually write tests, I feel like it's important to write your code as if you were, because unit testing should enforce good coding habits (The word 'should' is very important here).

The mindset of 'just get it done' encourages shortcuts that work ok for the short- and midterm, but crack over the long-term.

I've been in several situations where I had to explain that there is no "simply switch from service provider A to service provider B", but couldn't tell that it was because the entire application was tightly bound to the implementation of provider A. I've had to explain to clients that the work takes longer, but couldn't tell that it was because the previous employee left the code so unreadable that I had trouble finding out where to put my new code. I've had to explain to clients why the other page broke after deployment, but couldn't tell that it was because this totally unrelated page somehow had a connection with the feature that I was working on, only because the previous developer had failed to remove everything completely.

Do you "always" need to write unit tests though? Nah, if you're just trying some things out or still explore the possibilities, then don't bother. But if your code is going live at some point, then please do.

That being said, I find that unit testing isn't very accessible always. It takes a good amount of learning to understand what you're doing.

Collapse
 
skyjur profile image
Ski • Edited

You start realizing value of unit tests when you spent days of debugging high level tests to figure out why 1 line of code change broke them. Of course this only applies to large projects. In small/medium projects it can be perfectly effective to only have end-to-end tests. What unit tests are all about in essence is about testing individual components in isolation achieving healthy "test pyramid" thus reducing amount of high level tests needed.

Collapse
 
devdufutur profile image
Rudy Nappée

I tend to write integration tests over unit tests. I like them because they survive any code refactor and test the app or the api the way the user uses it. Also it could be used as functional spec. I keep Unit tests for testing my domain kayer when I am lazy or when preparing complex test case will over consume my time

Collapse
 
jonrandy profile image
Jon Randy 🎖️

Nope. I've been a professional developer for almost 30 years and have VERY rarely used any form of automated testing.

I've always thought (and seen plenty of evidence) that automated testing very much encourages a silo-isation of code knowledge, and really isn't good overall for teams working on a project. To my mind, if you are working on some code - you should UNDERSTAND that code and the ramifications of modifying it. Automated testing encourages a hands off approach and a reliance on the assumption that the tests are 'correct' and up to date - keeping the code being tested very much as a black box, with no real understanding being gained.

Collapse
 
theaccordance profile image
Joe Mainwaring

What do you think? Is it always better to write unit tests?

No, you should not default to always writing unit tests. Write them when the conditions of the development project/team/product necessitate a higher level of quality testing.

There are plenty of smaller projects where it adds zero value - like hackathons, MVPs, etc.

Collapse
 
taikedz profile image
Tai Kedzierski

Not wanting to write unit tests usually coincides with early-career state. You probably also see unit test code in tutorials performing testing for trivial matters (but remember, these are just tutorials).

The more you'll have dealt with complex systems, the more you will know the dread of making a change, lest it cause a breakage somewhere else - usually after deployment time.

Unit tests are a type of test that allow catching a lot of things early. Yes they can be a chore to write at first. But once you've got a habit of writing them, you also get a feel for it, and learn to put them together properly.

There's a fallacy that tends to see unit test code as "not real code." It is real code, and should be crafted with (near-)equal care.

In my teams, I've witnessed very silly breakages come out of small changes, and after unit testing was introduced, making non-breaking changes, and big changes at that, became much easier to implement, with much less fear or doubt. Making code unit-test-able does require some refactor, which is often the push-back you'll hear. The more valuable your code is for production, the more that push-back becomes invalid.

In many cases, unit tests can be the difference between

  • a bug found pre-commit, before anyone else sees it
  • the same bug being found post-shipment, in production, delivered to the customer

The more that idea is scary, then the more unit tests are going to be invaluable.

Collapse
 
perty profile image
Per Lundholm

This is a topic that are often discussed and there is no single answer other than "it depends ".

Unit test serve both as specification of intent and verification. If you write good tests, there's value in it. Bad tests, tied to implementation details, are just more code to maintain.

Unit test give faster feedback than integration tests, although there's value in both.

Even faster feedback is static typing. If you do DD and let context be modelled in types that make impossible states impossible, then you can easilier understand the code and it will be a lot safer.

Add to that idempotent functions and isolate side effects, as in functional programming, you get even less exposure to errors. Here Elm is a good example that is easy to learn.

Collapse
 
kallarari profile image
João Vitor Minosso

If you are in one big team and there is a lot of difference in knowledge, you should make unit tests for you don't have problems with the misuse of your component.