You inherited a codebase that's been running in production for years. It works, somehow. But nobody ever wrote tests for it, and now every change feels like a gamble.
The tech debt keeps growing. Refactoring is off the table because there's no safety net. New developers are afraid to touch anything. And the backlog of "add tests" tickets keeps getting pushed to next sprint, forever.
Writing tests for your own code is already tedious. Writing tests for someone else's code is painful. You don't know why decisions were made. You don't know what edge cases matter. You spend more time reading the code than testing it.
Developers avoid it. Managers can't prioritize it over features. The codebase stays untested, and the risk compounds with every deployment.
You want to modernize the codebase. Move to a newer framework. Clean up the architecture. But every refactor is a risk when there's nothing to verify that existing behavior still works.
So the code stays frozen. Technical debt accumulates. New features get bolted on top of old patterns because nobody dares to touch the foundation. The longer you wait, the harder it gets.
Writing tests for an existing codebase is a project unto itself. You need to understand the code, set up mocking, handle edge cases, and configure test infrastructure. For a large codebase, that easily turns into a multi-month effort.
Most teams try to do it incrementally: "we'll add tests as we touch files." In practice, that means coverage creeps up at 1-2% per quarter. At that rate, meaningful coverage is years away.