A Large Codebase Has No Automated Tests

Zero test coverage in a production system being actively modified. Nobody is confident enough to change the code safely.

What you are seeing

Every modification to this codebase is a gamble. The system has no automated tests. Changes are validated through manual testing, if they are validated at all. Developers work carefully. They know that any change could trigger failures in code they did not touch, because the system has no seams and no isolation. The only way to know if a change works is to deploy it and observe what breaks.

Refactoring is effectively off the table. Improving the design of the code requires changes that should not alter behavior. With no tests, nobody can verify that the behavior stayed the same. Developers choose to add code around existing code rather than improve it, because change is unsafe. The codebase grows more complex with every feature because improving the underlying structure carries too much risk.

The team knows the situation is unsustainable but cannot see a path out. “We should write tests” appears in every retrospective. The problem is that adding tests to an untestable codebase requires refactoring first - and refactoring requires tests to do safely. The team is stuck in a loop with no obvious entry point.

Common causes

Manual testing only

The team has relied on manual testing as the primary quality gate. Automated tests were never required, never prioritized, and never resourced. The codebase was built without testability as a design constraint. As a result, the architecture does not accommodate automated testing without structural change.

Making the transition requires a deliberate commitment. New code always gets tests, existing code gets tests when someone modifies it, and high-risk areas get retrofitted coverage first. Over months, the unsafe areas of the codebase shrink. A test suite that catches failures before production replaces the cycle of deploying to discover breakage.

Read more: Manual testing only

Tightly coupled monolith

Code without dependency injection, without interfaces, and without clear module boundaries cannot be tested without a major structural overhaul. Every function calls other functions directly. Every component reaches into every other component. Writing a test for one function requires instantiating the entire system.

Introducing seams - interfaces, dependency injection, module boundaries - makes code testable. This work is not glamorous, and its value stays invisible until the team starts writing tests. But seams are the prerequisite for meaningful test coverage in a tightly coupled system. Once the seams exist, you can test functions in isolation instead of instantiating the full application. Developers stop needing to deploy to find out if a change is safe.

Read more: Tightly coupled monolith

Pressure to skip testing

If management has historically prioritized features over tests, the codebase will reflect that history. Tests were deferred sprint by sprint. Technical debt accumulated. Today’s team inherits the decisions of teams that operated under different constraints. The codebase carries the record of every time testing lost to deadline pressure.

Reversing this history requires organizational commitment to treat test coverage as a delivery requirement, not as optional work that gets squeezed out when time is short. Without that commitment, the same pressure that created the untested codebase will prevent escaping it - and developers will keep gambling on every deploy.

Read more: Pressure to skip testing

How to narrow it down

  1. Can any single function in the codebase be tested without instantiating the entire application? If not, the architecture lacks the seams that unit tests need. Start with Tightly coupled monolith.
  2. Has the team ever had a sustained period of writing tests as part of normal development? If not, the practice was never established. Start with Manual testing only.
  3. Did historical management decisions consistently deprioritize testing? If test debt accumulated from external pressure, the organizational habit must change first. Only then can the technical situation improve. Start with Pressure to skip testing.

Ready to fix this? The most common cause is Manual testing only. Start with its How to Fix It section for week-by-week steps.