> A test will only catch an edge case you already thought of. If you thought of it anyway why just not fix the bug instead?
The reason I do this is to prevent the bug from re-occurring with future changes. The alternative is to just remember for every part of the system I work on all edge cases and past bugs, but sadly I simply do not have the mental capacity to do this, and honestly doubt if anyone does.
If a future change is relevant to an existing piece of code then the logic needs to be rethought from scratch. Your past tests have no guarantee that will be still relevant or comprehensive.
So skip the tests and work more on the code instead.
If a requirement changes, the test for that requirement obviously has to change. These tests breaking is normal (you had a requirement that "this is red", and a test ensuring "this is red", but now suddenly higher ups decide that "this is not red", so it's obvious why this test breaking is normal).
If a requirement doesn't change, the test for those requirements should not change, no matter what you change. If these tests break, it likely means they are at the wrong abstraction level or just plainly wrong.
Those are the things I look at. I don't even care if people call stuff "unit tests", "integration tests". I don't care about what should be mocked/faked/stubbed. I don't care about whatever other bikeshedding people want to go on.
E.g. if your app is an HTTP API, then you should be able to change your database engine without breaking tests like "user shouldn't be able to change the email of another user". And you should also be able to change your programming language without breaking any tests for user-facing behavior (e.g. "`GET /preferences` returns the preferences for the authenticated user").
E.g. if your code is a compiler, you should be able to add and remove optimizations without changing any tests, other than those specific to those optimizations (e.g. the test for "code with optimizations should behave the same as code without optimizations" shouldn't change, except for specific cases like compiling only with that optimization enabled or with some specific set of optimizations that includes this optimization).
The reason I do this is to prevent the bug from re-occurring with future changes. The alternative is to just remember for every part of the system I work on all edge cases and past bugs, but sadly I simply do not have the mental capacity to do this, and honestly doubt if anyone does.