Live data from Hacker News

Unit Tests Considered Harmful

shaiyallin.com

61–70 of 76 posts

Re: Unit Tests Considered Harmful

#61
I've seen this too many times: Developer gets obsessed with unit testing everything in the codebase. Tons of work, months later we have 100% coverage. Great. Then the rate of defects in production increases or stays steady. Why?

Confidence in units != confidence in your production system. I've observed that overconfidence in "units" tends to blind devs to other potential problem areas.

The most egregious example was an application release that wouldn't even start - there was an obvious bug in main that would have been caught by simply running the damn program and using your eyeballs. But the unit tests didn't catch it because main was tested in a mocked environment. Oops.

Likewise, I've seen similar regressions in quality control, user experience, performance, etc. - we know these things are critical to the real-world success of software, yet unit tests don't touch them.

There are software developers who are so overconfident in their unit tests that they ship code without ever bothering to run the application! Functional requirements be damned. "But the unit tests said it worked..." is not a professional excuse. Don't be that developer. Edit: to be clear, this is a message to myself as well. I was that developer a few times!

Re: Unit Tests Considered Harmful

#62
post #48
post #28

Earlier quoted context omitted.

I'll take it a step further than this. It doesn't matter if the client wants unit tests or not. If the developer has been hired to do the job, it's going to be up to that developer whether or not they feel unit tests will make the code better. If they do, they should do them. If they don't, they shouldn't. Caring about the client's opinions re: unit tests is a little like caring about their opinion re: the interior c…

If it is in the contract and specs (either way) then you do what you are paid to do.

Well of course. That's not relevant to the larger point, though.

Re: Unit Tests Considered Harmful

#64
OP here,

As some have noted, I’m not actually against tests. Quite the contrary - I’ve been practicing TDD since 2013. My approach to software is driving emergent design by TDD, initially via an E2E test, then via fast, integrative acceptance tests that exercise features while faking IO. I do write unit tests for very specific and pure pieces of software that embody a business domain, such as algorithms or validations.

What I abhor is compulsively writing mockist unit tests for all classes or functions with the goal of satisfying some coverage metrics. These are hurting you thrice: you waste time writing them and maintaining them; you get a false sense of confidence because you have “full coverage”; and when trying to refactor, they hold you back.

You can read more about my approach here: https://www.shaiyallin.com/post/fake-don-t-mock

Re: Unit Tests Considered Harmful

#65
post #17

Everyone talking about unit tests, and testing in general as a thing to achieve are missing it entirely. Tests aren't a thing to achieve, and talking about whether unit testing, mocks etc. are better or worse without context is pointless. The thing to achieve is having a code base that 1) works 2) can be changed easily and proved to be still working. Now that we know that we can start deciding "how" we can achieve th…

Very good advice. Additionally, I'd add: - What sort of testing can be achieved given limited time and resources? ...because nearly all organizations, no matter how quality-oriented they claim to be, will prioritize non-test code delivery over test code, leaving scarce time for test creation before shipment deadlines.

Not to pick on you specifically, but I tend to agree with other posters that testing (automated or otherwise) is just an element of programming. Like all elements it needs to be done to taste, but it's pretty essential.

A line of questioning: Do you have time to write clear code? Time for comments? Time to manually test your changes hundreds of times? Time to refactor existing code when adding new code? Time to remove dead code? Time to automate the testing while you still have the little state machine you are working on in your head? Time to add observability to spot performance issues? Time to consider your rollout plan? Time to keep on top of changes which are in use? etc...

Automated tests (including unit tests) are just one part of writing correct code. If you are asked, "How long is it going to take?" that implies finishing all aspects of coding required to get something correct into use. You prioritize that, not anyone else.

Re: Unit Tests Considered Harmful

#66
post #27
post #2

The target audience for unit tests is not the client, it is the developer. Unit tests allow you to change code with more confidence. 100% code coverage is not a useful aim, you should aim for 100% confidence in your code. Unit tests can also function as example code, that can't get out of date, since then the tests will fail. Testing for quality assurance is a different thing, usually called acceptance testing and so…

As the author points out, "What constitutes a unit? Is it a function? A class?" If you test to a function, or a class, then your tests imply that function or class must be present, with that specific API. In my experience, most people write unit tests for internal implementation details that are irrelevant to the business domain. They end up inhibiting code change rather than encouraging change, because anything chan…

>If you test to a function, or a class, then your tests imply that function or class must be present, with that specific API.

So what? Every implementation will have some basic structure. That structure can be modified if needed. The point of a unit test is not to posit that any particular thing exists, but that the things that do exist actually work.

>In my experience, most people write unit tests for internal implementation details that are irrelevant to the business domain. They end up inhibiting code change rather than encouraging change, because anything changes often require re-evaluating each failing test to see if it was meaningful in the first place - and if 100s of tests are no longer meaningful, it's easy to skip the couple of tests which are true regression tests.

If the internal implementation is not observable without a bunch of other bullshit, these tests can help instill confidence that the stuff actually works. If you don't test, or test the overall system, it takes much longer. There is such a thing as a pointless test but it is far more common in my experience to have stuff that isn't covered at all by tests. If your biggest problem is that you have to delete some tests that you made obsolete, that's perfectly ok.

>As the author writes, full end-to-end tests "are often slow, cumbersome, hard to debug and tend to be flaky."

Those types of tests are not unit tests.

>Instead, find the internal interfaces which tied to the business logic ("something that delivers value to a paying client"), and write the tests to that. You can use unit test frameworks for that sort of functional testing.

It isn't only the business logic that needs to be tested. Anything that is cumbersome to test "enough" in the overall system ought to be unit tested. At work I'm faced with a series of structures that are cumbersome to test in isolation and in totality. If I had unit tests I could make changes at least 3x faster.

Re: Unit Tests Considered Harmful

#67
post #19

I see unit tests as a form of written contract. You write down what matters. Everything else is as solid as a verbal contract.

That’s how it works too for medical software: the test proves that the specification has been implemented in a feature, that the feature kinda works, and as a bonus you get some code coverage.

Re: Unit Tests Considered Harmful

#68
post #51

Earlier quoted context omitted.

I can see that, but only because the dev has arguably already made the mistake of showing sales working features before tests are written. I've always been clear to say when something is a partial mockup to verify that I've understood what they're asking for.

Yes, but many places don't have a healthy work environment, and developers are generally younger, less confrontational, and less experienced at negotiating than management and sales.

True that. One of the major factors of my success as a software developer is a lack of fear (either through stupidity or bravery) of "taking on" toxic/unfair/destructive environments and people.

Re: Unit Tests Considered Harmful

#69
post #17

Everyone talking about unit tests, and testing in general as a thing to achieve are missing it entirely. Tests aren't a thing to achieve, and talking about whether unit testing, mocks etc. are better or worse without context is pointless. The thing to achieve is having a code base that 1) works 2) can be changed easily and proved to be still working. Now that we know that we can start deciding "how" we can achieve th…

I afraid in practice answering latter questions brings you to the former statements.

Re: Unit Tests Considered Harmful

#70
post #27

Earlier quoted context omitted.

As the author points out, "What constitutes a unit? Is it a function? A class?" If you test to a function, or a class, then your tests imply that function or class must be present, with that specific API. In my experience, most people write unit tests for internal implementation details that are irrelevant to the business domain. They end up inhibiting code change rather than encouraging change, because anything chan…

>If you test to a function, or a class, then your tests imply that function or class must be present, with that specific API. So what? Every implementation will have some basic structure. That structure can be modified if needed. The point of a unit test is not to posit that any particular thing exists, but that the things that do exist actually work. >In my experience, most people write unit tests for internal imple…

> Every implementation will have some basic structure.

Setting aside functional vs OO paradigms, even if you have a simple helper function like:

  def removeprefix(s, prefix):
    if s.startswith(prefix):
      return s[len(prefix):]
    return s
do you write tests for it? Or do you write tests for the higher level routines which call it? I think most write tests for the function.

If you write tests for the function then you hinder future refactoring from removeprefix(s, prefix) to s.removeprefix(prefix) once you switch to a Python which implements s.removeprefix (3.9, I think?)

For example, in red-green-refactor TDD, you are not supposed to change the tests when you refactor.

What you've ended up with are tests for the specific structure, and not the general goals.

> If you don't test, or test the overall system, it takes much longer.

Good thing neither I nor the linked-to author makes either of those arguments.

> it is far more common in my experience to have stuff that isn't covered at all by tests

Which is why I use coverage-based method to identify what need more tests. Coverage is a powerful tool, and easily misused.

> If your biggest problem is that you have to delete some tests that you made obsolete, that's perfectly ok.

The biggest problem is that you decide to not refactor because there are so many tests to delete, and you have to figure out if the failing test really is okay to delete (because it was implementation specific) vs. one that needs to be updated (eg, because it handles a regression case).

> Those types of tests are not unit tests

Correct! And no one said they were.

> At work I'm faced with a ...

That's fine. You do you.

Post reply on HN