If I explain myself or add nuance, it won't be a "hot take" anymore, but here goes...
- I've mostly worked on small teams, but have maintained fairly large codebases (I think the largest single repo I've worked in was about 1.5 million LoC). I've also maintained software used by other teams, though in fairly small software organizations (under 100 developers total).
- I've written code with 100% unit test coverage, and code with almost no coverage. The 100% coverage was in a library that was intended to be core functionality shared across multiple teams.
I definitely agree that they can be useful as both usage examples and as a way to enforce some rules (and consistency) in the API. But I'm not sure I'd go so far as to call that a "spec", because it's too easy to make a breaking change that isn't detected by unit tests. I also feel that mocking is often needed to prevent unit tests from becoming integration tests, but it often hides real errors while excessively limiting the amount of code that's actually being exercised.
I also think that actual integration tests are often a better demonstration of your API than unit tests are.
I haven't used any of these methods as much as I'd like to, but I suspect that each of them is strictly more useful than standard unit testing:
- contract tests (arguably just a form of unit testing, but not the way I've generally seen it done)
- property-based tests
- mutation tests
- preconditions & postconditions (with language support)