They’re still documenting how the code is supposed to behave. If they really never fail no matter how you change the code, you may not be testing the right things.
The issue is that too often they fail not because the code was incorrect, but because it changed and the test/mocks are incorrect. Higher level tests stay valid because they’re things like “none of the command line args should crash”.
Besides that, sometimes code just doesn’t change (say a basic math library). Then you’re mostly testing your compiler, which is useful but an intentional approach would be better.
I agree with your first point. But there’s somebody out there telling us that a true unit test has no mocks. Or something.
Unit tests do come in handy when building a maths library.l or similar. Not in terms of catching a regression, but to help build it in the first place. One of the few places where TDD might actually be helpful.
Not everything is amenable to unit tests, but if you can design a module to be unit testable, you should. And unit tests give others more confidence in your code — they allow other people to modify your code with confidence as well.
In the pragmatic programmer the author talks about unit testing as a great way to learn how to write testable code. They mention the benefits of that sort of code and how they don't always write unit tests as that's not the most important part.
I prefer integration testing over unit testing because each test case covers many more lines of code (since it also traverses dependencies). You can use mocks and stubs to allow the test suite to reset/set the state of the system between each test case so integration tests don't have to be brittle, unreliable or require launching other services on the side. I find that it's a good architectural pattern if the main state stores in a software can be easily substituted with mocks or stubs; in my experience, this makes the software more reliable, easier to maintain and more testable.
This. I have nothing against unit testing; there's been times when a unit test (often written by someone else) has stopped me pushing some truly stupid code to production. But when I started developing my canvas library (for fun, not work) I decided early on that unit testing every line of code was not only sucking the joy from the work, but also too hard to cover all the edge cases of what I was trying to deliver: responsive, interactive, animated graphics, often controlled by user interaction with the canvas element. So instead I developed a big bunch of demos which try to cover the full functionality of the library, which I can visually check locally before pushing code changes to the repo[1].
The big drawback is I have to check all these tests/demos manually (across browsers and devices) before releasing a new version of the library into the wild. Automating that process is on my list of Things To Do - if anyone has suggestions/insights into current tooling/testing suites that could help me then I'm very willing to listen and learn!